No KYC — no ID, no selfie, no documents. Pay in crypto: BTC, USDT, USDC, ETH, SOL, LTC
Get started

API reference

Orders

List the plans and their prices, buy a plan from the balance (new service or more traffic) and read your past orders.

Last updated: · 5 min read

Endpoints on this page

  • GET /v1/catalog/products: Products, plans and prices
  • POST /v1/orders: Buy a plan from the balance (new service or more traffic)
  • GET /v1/orders: List orders
  • GET /v1/orders/{orderId}: Get an order

Base URL https://crawlrelay.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": "Rotating residential proxies",
      "description": "Rotating and sticky residential IPs for scraping public data, with country and city targeting (US state and ZIP code, ASN at no extra cost), billed per GB with traffic that never expires. Paid in crypto, no KYC.",
      "unit": "GB",
      "plans": [
        {
          "id": "res-10",
          "productId": "residential",
          "name": "Build",
          "quantity": 10,
          "unit": "GB",
          "durationDays": null,
          "price": "5.94",
          "pricePerUnit": "0.59",
          "popular": false,
          "features": [
            "≈200,000 HTML pages",
            "Small production jobs",
            "Traffic does not expire"
          ],
          "available": true,
          "countries": null
        }
      ]
    }
  ]
}

Code examples

curl
curl -s "https://crawlrelay.com/api/v1/catalog/products"
Python
import os
import requests

API = "https://crawlrelay.com/api/v1"

r = requests.get(f"{API}/catalog/products", timeout=30)
r.raise_for_status()
print(r.json())
Node.js
// Node.js 18+ (built-in fetch), ES module
const API = 'https://crawlrelay.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 or more traffic)

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" }.
  • New rotating 4G/5G traffic (per GB): { "planId": "mgb-10" } (a traffic subscription with productId: "mobile-gb", delivered in fulfillment.residentialSubscriptionId).
  • Add traffic to an existing subscription: { "planId": "res-10", "options": { "subscriptionId": "res_9x2m4k" } }: the plan must belong to the subscription's product.

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

NameInTypeRequiredDescription
Idempotency-KeyheaderstringNoUnique key (e.g. a UUID) to safely retry a POST. Kept 24 h. — max. 128 characters

Request body

FieldTypeRequiredDescription
planIdstringYes—
quantityintegerNo1–100, default 1
optionsobjectNo—
Example: Residential
{
  "planId": "res-10"
}
Example: Mobile Traffic
{
  "planId": "mgb-10"
}

Response 201 Created

{
  "id": "ord_4f8k2m9q",
  "status": "completed",
  "productId": "residential",
  "planId": "res-10",
  "planName": "Build",
  "quantity": 1,
  "unitPrice": "5.94",
  "subtotal": "5.94",
  "discount": "0.00",
  "total": "5.94",
  "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
curl -s -X POST "https://crawlrelay.com/api/v1/orders" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"planId":"res-10"}'
Python
import os, uuid
import requests

API = "https://crawlrelay.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
// Node.js 18+ (built-in fetch), ES module
import { randomUUID } from 'node:crypto';

const API = 'https://crawlrelay.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

NameInTypeRequiredDescription
pagequeryintegerNo≥ 1, default 1
perPagequeryintegerNo1–100, default 20
statusquerycompleted · cancelledNoOrders are created already paid (debited from the balance). completed — paid and delivered (credentials available immediately).
productIdquerystringNoProduct id from the catalogue. Values for CrawlRelay: residential (GB) and mobile-gb (rotating 4G/5G traffic per GB). Clients must tolerate unknown values.

Response 200 OK

{
  "data": [
    {
      "id": "ord_4f8k2m9q",
      "status": "completed",
      "productId": "residential",
      "planId": "res-10",
      "planName": "Build",
      "quantity": 1,
      "unitPrice": "5.94",
      "subtotal": "5.94",
      "discount": "0.00",
      "total": "5.94",
      "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
curl -s "https://crawlrelay.com/api/v1/orders" \
  -H "Authorization: Bearer $API_KEY"
Python
import os
import requests

API = "https://crawlrelay.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
// Node.js 18+ (built-in fetch), ES module
const API = 'https://crawlrelay.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

NameInTypeRequiredDescription
orderIdpathstringYes—

Response 200 OK

{
  "id": "ord_4f8k2m9q",
  "status": "completed",
  "productId": "residential",
  "planId": "res-10",
  "planName": "Build",
  "quantity": 1,
  "unitPrice": "5.94",
  "subtotal": "5.94",
  "discount": "0.00",
  "total": "5.94",
  "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
curl -s "https://crawlrelay.com/api/v1/orders/ord_4f8k2m9q" \
  -H "Authorization: Bearer $API_KEY"
Python
import os
import requests

API = "https://crawlrelay.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
// Node.js 18+ (built-in fetch), ES module
const API = 'https://crawlrelay.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());

From $0.50/GB · no KYC

Get started