30i VPN

Customer API

Use your wallet to order subscriptions and track activation from your application.

Manage API keys

1. Authentication

Create an API key in your account. Copy it when shown; the secret cannot be viewed again. Send it in the Authorization: Bearer YOUR_API_KEY header on every request. Use HTTPS and keep the key on your server. Revoke it in your account if exposed. Each account can have five active keys.

Base URL: https://30i.click/api/v1. Requests and responses use JSON. Prices are integer cents (minor units); for example 899 means 8.99 USD. Dates use UTC ISO 8601. Limit: 60 authenticated requests per minute per account and 60 new order attempts per hour.

2. Check available balance

GET /balance

curl https://30i.click/api/v1/balance \
  -H 'Authorization: Bearer YOUR_API_KEY'
{"data":{"currency":"USD","balance_minor":1000,"held_minor":0,"available_minor":1000}}

available_minor is the amount you can spend. Pending orders reserve funds in held_minor. Add funds through your account before ordering.

3. List active plans

GET /plans

curl https://30i.click/api/v1/plans \
  -H 'Authorization: Bearer YOUR_API_KEY'
{"data":[{"id":"monthly","name":"Monthly subscription","price_minor":899,"currency":"USD","duration_days":null,"duration_months":1}]}

Use a returned id when ordering. Custom plans have IDs such as custom:3 and specify duration_days. The response includes enabled plans only; prices can change.

4. Place an order

POST /orders. Provide the activation email, plan ID, and a unique Idempotency-Key header. The optional max_price_minor prevents an order if the plan price has risen above your limit.

curl -X POST https://30i.click/api/v1/orders \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-12345' \
  -d '{"plan_id":"monthly","activation_email":"customer@example.com","max_price_minor":899}'
{"data":{"id":"48a8b537-706d-4571-b238-bb7c39d0d0ba","plan_id":"monthly","activation_email":"customer@example.com","price_minor":899,"currency":"USD","duration_days":null,"status":"queued","created_at":"2026-10-01T10:00:00Z","activated_at":null,"expires_at":null,"message":null},"meta":{"poll_after_seconds":30}}

A new accepted request returns HTTP 202 and a Location header. It enters the activation queue; the response does not confirm activation. The worker checks new orders about every five minutes. Keep the same idempotency key when retrying after a timeout: a replay returns the same order with HTTP 200 and never reserves a second payment. Reusing that key with different order details returns 409. Keys may contain 8–100 letters, digits, ., _, :, or -.

Wallet funds are held while activation is pending and charged only when confirmed. A failed order releases the hold. A subscription email already active or pending cannot be ordered again, even from another account. Once fully cancelled or expired, it can be used for a new order.

5. Follow an order

GET /orders/{id} or GET /orders?limit=20&offset=0

curl https://30i.click/api/v1/orders/ORDER_UUID \
  -H 'Authorization: Bearer YOUR_API_KEY'
curl 'https://30i.click/api/v1/orders?limit=20&offset=0' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Possible statuses: queued, processing, active, review_required, failed, cancelling, cancelled, expired. Only active confirms activation. When review_required appears, keep the order ID and contact support; do not send a replacement order. Results show orders for your account only.

Errors

Errors return JSON such as:

{"error":{"code":"insufficient_balance","message":"Insufficient available balance."}}

HTTP 400 invalid JSON, 401 missing or revoked key, 404 missing order, 409 balance/email/price/idempotency conflict, 413 body too large, 415 wrong content type, 422 invalid fields, 429 rate limit, 503 sales unavailable. For 500 or a network timeout, retry with the same idempotency key.