Orax Orax
Sign in
REST · OAuth 2.0 · v1

API for developers

Manage hosting, domains, monitoring and your wallet from your own code. REST, OAuth 2.0, predictable responses.

205
endpoints
11
need no token
13
scopes
17
sections

Start in a minute

The first request works right now — no sign-up needed for it.

1. Public data

Copy and run it — real domain prices come back.

curl https://orax.uz/api/v1/domains/tlds

2. Your data

Get an OAuth 2.0 token and call your own account.

curl https://orax.uz/api/v1/services \
  -H "Authorization: Bearer <access_token>"

What the API covers

Sections and operation counts are read from the reference itself, so this list cannot drift from what ships.

Authorization

OAuth 2.0, authorization code. Mobile apps and SPAs must use PKCE — they cannot ship a client secret.

0. Register your application

Get a client_id and set your redirect URI. Without this step the next two have nothing to run against.

Register an application

1. Send the user to the consent screen

They see which permissions you ask for, then come back to your redirect_uri with ?code=…

https://orax.uz/oauth/authorize
  ?client_id=<client_id>
  &redirect_uri=https://your.app/callback
  &response_type=code
  &scope=profile services:read monitors:read
  &state=<random>
  &code_challenge=<base64url(sha256(verifier))>
  &code_challenge_method=S256

2. Exchange the code for a token

The response carries an access token (15 days) and a refresh token (30 days).

curl -X POST https://orax.uz/oauth/token \
  -d grant_type=authorization_code \
  -d client_id=<client_id> \
  -d redirect_uri=https://your.app/callback \
  -d code_verifier=<verifier> \
  -d code=<code_from_redirect>
{
  "token_type": "Bearer",
  "expires_in": 1296000,
  "access_token": "eyJ0eXAiOiJKV1Qi...",
  "refresh_token": "def50200a1b2c3..."
}

3. Refresh without asking the user again

grant_type=refresh_token at the same URL. Scopes are granted at consent time — a token can never gain one the user did not approve.

Scopes

Ask for the minimum: an uptime dashboard needs monitors:read and nothing that spends money.

profileRead your Orax profile
services:readView your services
services:writeManage your services (domains, databases, FTP)
orders:readView your orders
orders:writeCreate and pay orders on your behalf
wallet:readView your wallet balance and transactions
wallet:writeTop up your wallet
ai:readView AI agent settings, conversations and project insights
ai:writeRun the AI agent and change its settings, files and insights
domains:readView your domain registrations
domains:writeRegister domains on your behalf (charges your wallet)
monitors:readView your uptime monitors and their history
monitors:writeCreate and manage your uptime monitors

This list is read from the authorization server itself. Administrative access is never granted to third parties.

Conventions

The same rules across every endpoint — learn them once.

Sandbox

Mark an application as sandbox: its tokens read everything the scopes allow and every write is refused with error=sandbox_read_only. Nothing gets bought while you debug.

Money is in cents

Billing is always USD, amounts are integers in minor units (usd_cents). Other currencies are display-only.

Lists

Always data + meta with page, per_page, total and last_page. per_page is capped at 50.

Errors

error is a stable machine key, message is translated prose for humans. Branch on error, never on message.

Language

?lang=uz|ru|en on public endpoints resolves translatable fields to one string instead of an object.

Idempotency-Key

A header for requests that move money. A retry with the same key within 24h is not charged again.

Sections can be switched off

A disabled section 404s over the API too. The live list arrives in GET /api/v1/me, so your app hides the tab instead of showing an error.

A list response

{
  "data": [ { "id": 12, "label": "Start", "status": "active" } ],
  "meta": { "page": 1, "per_page": 20, "total": 43, "last_page": 3 }
}

An error response

{
  "error": "insufficient_funds",
  "message": "На балансе недостаточно средств."
}

Safe retries

If the connection drops, repeat the request with the same key — there is no second charge.

curl -X POST https://orax.uz/api/v1/orders \
  -H "Authorization: Bearer <access_token>" \
  -H "Idempotency-Key: 8f14e45f-ea0b-4c1e-9f2d-71c0a3d9b201" \
  -H "Content-Type: application/json" \
  -d '{"plan_id": 7, "domain": "example.uz"}'

Status codes

What you actually have to handle.

  • 200 / 201success; creation answers 201
  • 401token missing or expired
  • 403the token lacks the required scope
  • 404not found, or the section is switched off
  • 409a request with this Idempotency-Key is already running
  • 422validation or business-rule refusal
  • 429rate limit exceeded

Limits: 90 requests per minute on the main API, 60 on the reseller API, 20 on WHOIS domain checks.

Open data

No token, no registration.

  • GET /api/v1/domains/tldsDomain zone price book
  • GET /api/v1/domains/check?domain=WHOIS availability check
  • GET /api/v1/kbKnowledge base
  • GET /api/v1/blogBlog posts
  • GET /api/v1/reviewsReviews and average rating
  • GET /api/v1/glossaryHosting glossary
  • GET /api/v1/templatesSite templates with live demos
  • GET /api/v1/currenciesCurrencies and the rate per USD
  • GET /api/v1/statusPlatform status and incidents

Your account

An OAuth 2.0 token with the right scope.

  • GET /api/v1/meprofile · Profile, language, currency, available sections
  • GET /api/v1/servicesservices:read · Your services and their state
  • GET /api/v1/services/{id}/uptimeservices:read · Uptime, outages and SLA compensation
  • GET /api/v1/services/{id}/securityservices:read · Security score for a service
  • POST /api/v1/domainsdomains:write · Register a domain
  • GET /api/v1/monitorsmonitors:read · Uptime monitors
  • POST /api/v1/ordersorders:write · Create and pay an order
  • GET /api/v1/walletwallet:read · Balance and transaction history

Beyond REST

Three separate surfaces for the cases plain REST does not cover.

Reseller API and webhooks

A separate key (rsk_…), wholesale prices and provisioning tagged with your own client_ref. Service events arrive as a signed webhook — verify the signature, or anyone can post to you.

Verifying the X-Orax-Signature header

$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', $body, $yourWebhookSecret);

if (! hash_equals($expected, $_SERVER['HTTP_X_ORAX_SIGNATURE'] ?? '')) {
    http_response_code(403); exit;
}

$event = json_decode($body, true); // service.provisioned | .suspended | .terminated ...

MCP for AI agents

JSON-RPC 2.0 over the Model Context Protocol: the agent gets a tool list filtered by its token's scopes. Version 1 is read-only — money and destructive actions stay with a human.

Endpoint to connect

https://orax.uz/api/v1/mcp

The client finds where to send you to log in on its own: we publish the OAuth discovery documents, and a refusal without a token names them in its header. No key has to be handed out separately.

Claude Code

claude mcp add --transport http orax https://orax.uz/api/v1/mcp

VS Code

// .vscode/mcp.json
{
  "servers": {
    "orax": { "type": "http", "url": "https://orax.uz/api/v1/mcp" }
  }
}

No Orax extension to install: both clients speak MCP themselves. One address and your editor sees your account.

curl -X POST https://orax.uz/api/v1/mcp \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

The client has to be set up by hand: we do not support dynamic client registration (RFC 7591), so a one-click “add” button in some apps will not work. Pasting the address yourself works everywhere.

Resellers: every client at once

A separate endpoint for partners, on your existing rsk_… key — no OAuth. The agent sees all your clients' services together: filter by client tag, by status or by renewal date, and every row says whether the renewal is already covered.

https://orax.uz/api/v1/reseller/mcp

Manifest for directories — its tool list is generated from the server itself, so it cannot go stale:

https://orax.uz/.well-known/mcp/server.json

Embeddable blocks

The uptime badge is a plain image: no token, no CORS trouble. The template demo is served sandboxed, so it is safe in an iframe.

<!-- uptime badge -->
<img src="https://orax.uz/badge/<token>" alt="uptime">

<!-- live template demo -->
<iframe src="https://orax.uz/templates/12/preview" loading="lazy"></iframe>

How our API works

Scopes are separate

Grant an uptime dashboard read access to monitors only — it still cannot spend your money on domains.

Secrets stay out

Server, FTP and database passwords have no API representation. A read token never becomes root on your machine.

Money is guarded

Purchases accept an Idempotency-Key, so a repeated request never charges twice.

Predictable responses

Lists always carry data and meta; refusals return a stable error key, not a translated sentence.

Versioning and compatibility

The version is in the URL: /api/v1. Within v1 we may add endpoints and new fields to responses — your code should tolerate fields it does not know. Removing a field, renaming one or changing what a response means requires a new version, never a silent change.

Ready to build?

Every endpoint, schema and status code lives in the OpenAPI reference.