CDNShark Documentation

Reseller API

← Back to Documentation

Reseller API — Ordering Services

Four product lines can be ordered for a customer: CDN, Cloud VPS, shared hosting and mailbox seats. Every order debits your credit balance immediately at your wholesale price.

Idempotency is required

All four ordering endpoints require an Idempotency-Key header. Send a unique value — a UUID is ideal — for each order attempt, and reuse the same value when retrying.

Idempotency-Key: 3f8a2c14-9d4e-4b71-a0c2-5e6f8b1d2a33

This is what stops a network timeout from provisioning and charging twice:

  • Same key, same body, already completed → the original response is replayed with an Idempotency-Replayed: true header. Nothing is charged again.
  • Same key, same body, still running → 409. Retry in a moment.
  • Same key, different body → 422. Use a fresh key for a new order.
  • No key at all → 400.

If the request fails with a 5xx, the key is released so a genuine retry re-runs the order.

Check your balance first

Ordering beyond your balance returns 402 and provisions nothing:

{
  "message": "Insufficient credit. This service costs $15.00 but your balance is $4.20. Top up and try again.",
  "required": 15.00,
  "credit_balance": 4.20,
  "shortfall": 10.80
}

Order a CDN service

curl -X POST "https://cdnshark.com/api/reseller/services" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "customer_id": 4210,
    "plan_id": 3,
    "domain_name": "cdn.example.com"
  }'

Returns 201 with the order, the created service, the amount charged and your new balance.

Order a Cloud VPS

POST /api/reseller/vps
{
  "customer_id": 4210,
  "plan_id": 11,
  "region_id": 2,
  "os_key": "ubuntu-24.04",
  "hostname": "web01.example.com",
  "billing_cycle": "monthly",
  "ssh_pubkey": "ssh-ed25519 AAAA..."
}

billing_cycle is one of monthly, quarterly, yearly or 2year; longer cycles carry a discount, quoted per cycle on the plan endpoint. Supply either ssh_pubkey or password.

VPS builds are asynchronous. The order is charged straight away; the instance appears with status pending and becomes running when Proxmox finishes. Subscribe to the reseller.service.active webhook rather than polling.

Order shared hosting

POST /api/reseller/hosting
{
  "customer_id": 4210,
  "plan_id": 7,
  "primary_domain": "example.com",
  "username": "examplecom"
}

The primary_domain must already be an active CDN domain owned by the same customer — hosting sits behind the CDN, so order the CDN service first. username is 3–32 characters, lowercase letters and digits, starting with a letter, and unique platform-wide.

Order mailbox seats

POST /api/reseller/mail
{"customer_id": 4210, "plan_id": 9, "quantity": 5}

This buys a quantity of seats. Your customer then creates the individual mailboxes from their own portal.

Suspend and reactivate a service

POST /api/reseller/services/{id}/suspend
POST /api/reseller/services/{id}/unsuspend

POST /api/reseller/vps/{id}/suspend
POST /api/reseller/vps/{id}/unsuspend

POST /api/reseller/hosting/{id}/suspend
POST /api/reseller/hosting/{id}/unsuspend

Unlike suspending a customer, this genuinely stops the service: CDN delivery is cut, a VPS is powered off, a hosting account is disabled. Suspension does not refund credit.

Check what a product is available

Product lines can be switched off platform-wide. Before showing a product in your storefront, check:

GET /api/reseller/products

Ordering a product that is switched off returns 403.