Endpoints on this page
GET /v1/catalog/products: Products, plans and pricesPOST /v1/orders: Buy a plan from the balance (new service, more traffic, or port extension)GET /v1/orders: List ordersGET /v1/orders/{orderId}: Get an order
Base URL https://japanproxies.com/api/v1. Authentication, errors and limits: see the API overview.
Products, plans and prices
GET/v1/catalog/products
Every product with its plans and prices, exactly as charged when you order.
Public: no API key needed.
Response 200 OK
{
"data": [
{
"id": "residential",
"name": "Residential proxies for Japan and East Asia",
"description": "Rotating and sticky residential IPs in Japan, South Korea, Taiwan and Hong Kong, chosen by country code in the proxy username, billed per GB with traffic that never expires. Paid in crypto, no KYC.",
"unit": "GB",
"plans": [
{
"id": "res-10",
"productId": "residential",
"name": "Standard",
"quantity": 10,
"unit": "GB",
"durationDays": null,
"price": "6.60",
"pricePerUnit": "0.66",
"popular": false,
"features": [
"Weekly checks for one market",
"All four countries",
"Traffic never expires"
],
"available": true,
"countries": null
}
]
}
]
}Code examples
curl -s "https://japanproxies.com/api/v1/catalog/products"import os
import requests
API = "https://japanproxies.com/api/v1"
r = requests.get(f"{API}/catalog/products", timeout=30)
r.raise_for_status()
print(r.json())// Node.js 18+ (built-in fetch), ES module
const API = 'https://japanproxies.com/api/v1';
const res = await fetch(`${API}/catalog/products`);
if (!res.ok) throw new Error((await res.json()).error?.message ?? `HTTP ${res.status}`);
console.log(await res.json());Buy a plan from the balance (new service, more traffic, or port extension)
POST/v1/orders
Always paid from the prepaid balance: the price is computed by the API (catalogue price × quantity), the balance is debited, the service is created or extended and the order comes back completed with its fulfillment. The proxy credentials are available at once.
- New residential traffic:
{ "planId": "res-10" }. - Add traffic to an existing subscription:
{ "planId": "res-10", "options": { "subscriptionId": "res_9x2m4k" } }: the plan must belong to the subscription's product. - New mobile port(s):
{ "planId": "mob-a-30d", "quantity": 1, "options": { "country": "JP" } }, optionally withcarrier(see the carriers of a country in Mobile ports). Zone plans only cover the countries of their zone (422onoptions.countryotherwise). - Extend a mobile port:
{ "planId": "mob-a-7d", "options": { "portId": "mob_2v8k1q" } }adds the plan's duration toexpiresAt.
Balance too low → 402 insufficient_balance, with the missing amount and a suggested top-up in error.details (missing, suggestedTopUp). Nothing is debited on any error. To pay the difference, start a top-up carrying the same request in purchase (POST /v1/topups): the plan is bought as soon as the top-up is credited.
Authentication: API key in the Authorization: Bearer API_KEY header.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key | header | string | No | Unique key (e.g. a UUID) to safely retry a POST. Kept 24 h. — max. 128 characters |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
planId | string | Yes | — |
quantity | integer | No | 1–100, default 1 |
options | object | No | — |
{
"planId": "res-10"
}{
"planId": "mob-a-30d",
"quantity": 1,
"options": {
"country": "JP",
"carrier": "ntt-docomo",
"autoRenew": true
}
}{
"planId": "mob-a-7d",
"options": {
"portId": "mob_2v8k1q"
}
}{
"planId": "mob-a-30d",
"options": {
"country": "JP",
"carrier": "ntt-docomo"
}
}Response 201 Created
{
"id": "ord_4f8k2m9q",
"status": "completed",
"productId": "residential",
"planId": "res-10",
"planName": "Standard",
"quantity": 1,
"unitPrice": "6.60",
"subtotal": "6.60",
"discount": "0.00",
"total": "6.60",
"promoCode": null,
"currency": "USD",
"topUpId": null,
"options": {},
"fulfillment": {
"residentialSubscriptionId": "res_9x2m4k",
"mobilePortIds": []
},
"createdAt": "2026-10-05T14:03:11Z",
"paidAt": "2026-10-05T14:03:11Z"
}Code examples
curl -s -X POST "https://japanproxies.com/api/v1/orders" \
-H "Authorization: Bearer $API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"planId":"res-10"}'import os, uuid
import requests
API = "https://japanproxies.com/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['API_KEY']}", "Idempotency-Key": str(uuid.uuid4())}
r = requests.post(f"{API}/orders", headers=HEADERS, json={"planId": "res-10"}, timeout=30)
r.raise_for_status()
print(r.json())// Node.js 18+ (built-in fetch), ES module
import { randomUUID } from 'node:crypto';
const API = 'https://japanproxies.com/api/v1';
const res = await fetch(`${API}/orders`, {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.API_KEY}`, 'Idempotency-Key': randomUUID(), 'Content-Type': 'application/json' },
body: JSON.stringify({ planId: 'res-10' }),
});
if (!res.ok) throw new Error((await res.json()).error?.message ?? `HTTP ${res.status}`);
console.log(await res.json());List orders
GET/v1/orders
Authentication: API key in the Authorization: Bearer API_KEY header.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page | query | integer | No | ≥ 1, default 1 |
perPage | query | integer | No | 1–100, default 20 |
status | query | completed · cancelled | No | Orders are created already paid (debited from the balance). completed — paid and delivered (credentials available immediately). |
productId | query | string | No | Product id from the catalogue. Values for JapanProxies: residential (GB) and mobile (dedicated 4G/5G ports). Clients must tolerate unknown values. |
Response 200 OK
{
"data": [
{
"id": "ord_4f8k2m9q",
"status": "completed",
"productId": "residential",
"planId": "res-10",
"planName": "Standard",
"quantity": 1,
"unitPrice": "6.60",
"subtotal": "6.60",
"discount": "0.00",
"total": "6.60",
"promoCode": null,
"currency": "USD",
"topUpId": null,
"options": {},
"fulfillment": {
"residentialSubscriptionId": "res_9x2m4k",
"mobilePortIds": []
},
"createdAt": "2026-10-05T14:03:11Z",
"paidAt": "2026-10-05T14:03:11Z"
}
],
"pagination": {
"page": 1,
"perPage": 20,
"total": 1,
"totalPages": 1
}
}Code examples
curl -s "https://japanproxies.com/api/v1/orders" \
-H "Authorization: Bearer $API_KEY"import os
import requests
API = "https://japanproxies.com/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
r = requests.get(f"{API}/orders", headers=HEADERS, timeout=30)
r.raise_for_status()
print(r.json())// Node.js 18+ (built-in fetch), ES module
const API = 'https://japanproxies.com/api/v1';
const res = await fetch(`${API}/orders`, {
headers: { Authorization: `Bearer ${process.env.API_KEY}` },
});
if (!res.ok) throw new Error((await res.json()).error?.message ?? `HTTP ${res.status}`);
console.log(await res.json());Get an order
GET/v1/orders/{orderId}
Authentication: API key in the Authorization: Bearer API_KEY header.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
orderId | path | string | Yes | — |
Response 200 OK
{
"id": "ord_4f8k2m9q",
"status": "completed",
"productId": "residential",
"planId": "res-10",
"planName": "Standard",
"quantity": 1,
"unitPrice": "6.60",
"subtotal": "6.60",
"discount": "0.00",
"total": "6.60",
"promoCode": null,
"currency": "USD",
"topUpId": null,
"options": {},
"fulfillment": {
"residentialSubscriptionId": "res_9x2m4k",
"mobilePortIds": []
},
"createdAt": "2026-10-05T14:03:11Z",
"paidAt": "2026-10-05T14:03:11Z"
}Code examples
curl -s "https://japanproxies.com/api/v1/orders/ord_4f8k2m9q" \
-H "Authorization: Bearer $API_KEY"import os
import requests
API = "https://japanproxies.com/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['API_KEY']}"}
r = requests.get(f"{API}/orders/ord_4f8k2m9q", headers=HEADERS, timeout=30)
r.raise_for_status()
print(r.json())// Node.js 18+ (built-in fetch), ES module
const API = 'https://japanproxies.com/api/v1';
const res = await fetch(`${API}/orders/ord_4f8k2m9q`, {
headers: { Authorization: `Bearer ${process.env.API_KEY}` },
});
if (!res.ok) throw new Error((await res.json()).error?.message ?? `HTTP ${res.status}`);
console.log(await res.json());