For developers
NAX API
Create photoreal AI video from your own backend. The API runs the exact same rendering pipeline, credit pricing and content safety as the Studio — everything you generate lands in your Library, watermark-free.
Start here
Overview
The NAX API is a small, predictable REST surface: create a render, poll it, download the file. There is no SDK to install and no webhook to configure — every call is plain HTTPS with a JSON body and a bearer key.
| Property | Value |
|---|---|
| Base URL | https://naxaigc.com/api/public/v1 |
| Auth | Authorization: Bearer nax_live_… |
| Content type | application/json (UTF-8) |
| Aspect ratios | 9:16 (vertical) · 16:9 (landscape) |
| Length | 8–64 seconds, in 8-second clips |
| Resolutions | 720p · 1080p · 2K · 4K |
| Output | MP4, H.264, with sound, no watermark |
| Billing | Credits from the key owner's own balance |
Everything the API produces is also visible in the Studio Library for the same account, so your team can review, re-download or reuse renders that your code created.
Core concepts
Render. One job. It holds your brief, the format, the credits charged, its status and — once finished — the video file.
Clip. Video is generated in 8-second clips. A 32-second render is four chained clips, each continuing the subject, wardrobe and location of the one before it. This is why duration must be a multiple of 8.
Engine. The quality/price tier of the generator:
| Engine | Best for | Credits per 5s |
|---|---|---|
| nax-cine | Hero ads, faces, cinematic realism | 140 |
| nax-flow | Everyday social content, fast turnaround | 45 |
| nax-draft | Cheap previews and storyboard tests | 16 |
| nax-i2v | Animating a still image or product photo | 60 |
| nax-ultra | NAX Ultra — flagship realism, our most lifelike people & motion | 320 |
Credit. The single unit of billing across Studio, NAX Mode and the API — about RM 0.25 each. Every account also receives 50 free credits every day (08:00 Malaysia time, no rollover), and free credits are always spent before paid ones.
Keys & authentication
Sign in and open Studio → Developer API to create a key. Keys look like nax_live_… and the full value is shown only once, at creation — we store only a one-way fingerprint, so nobody (including us) can read your key back afterwards.
Authorization: Bearer nax_live_your_key
Each key belongs to exactly one account and can only spend that account's credits and read that account's renders. You may hold several keys — one per app or environment — and Rename, Reset (rotate) or Revoke any of them at any time. Revoking takes effect immediately on the next call.
Quickstart
Start a 16-second vertical render, then poll it until the file is ready.
curl -X POST https://naxaigc.com/api/public/v1/videos \
-H "Authorization: Bearer nax_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A barista pours latte art in a sunlit Penang kopitiam, handheld camera, morning ambience",
"aspect": "9:16",
"duration": 16,
"resolution": "1080p",
"engine": "nax-cine",
"language": "Bahasa Melayu",
"title": "Kopitiam morning"
}'
# → { "id": "…", "status": "rendering", "credits": 450, "clips": 2,
# "poll_url": "/api/public/v1/videos/…" }const key = process.env.NAX_API_KEY;
const headers = { Authorization: `Bearer ${key}` };
const start = await fetch("https://naxaigc.com/api/public/v1/videos", {
method: "POST",
headers: { ...headers, "Content-Type": "application/json" },
body: JSON.stringify({ prompt: "…", aspect: "9:16", duration: 16 }),
}).then((r) => r.json());
let render = start;
while (render.status === "rendering" || render.status === "queued") {
await new Promise((r) => setTimeout(r, 8000)); // poll every 5–10s
render = await fetch(`https://naxaigc.com/api/public/v1/videos/${start.id}`, { headers })
.then((r) => r.json());
console.log(render.status, render.progress + "%");
}
if (render.status === "completed") console.log(render.download_url);import os, time, requests
H = {"Authorization": f"Bearer {os.environ['NAX_API_KEY']}"}
B = "https://naxaigc.com/api/public/v1"
job = requests.post(f"{B}/videos", headers=H, json={
"prompt": "…", "aspect": "16:9", "duration": 24, "resolution": "1080p",
}).json()
while True:
r = requests.get(f"{B}/videos/{job['id']}", headers=H).json()
if r["status"] in ("completed", "failed"):
break
print(r["status"], r.get("progress"))
time.sleep(8)
print(r.get("download_url"))$ch = curl_init("https://naxaigc.com/api/public/v1/credits");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("NAX_API_KEY")],
]);
$balance = json_decode(curl_exec($ch), true);
// → ["paid_credits" => 1200, "free_credits" => 50, "total_credits" => 1250, …]Endpoints
POST/api/public/v1/videos
GET/api/public/v1/videos/{id}
GET/api/public/v1/renders
GET/api/public/v1/credits
Any other method on these paths returns 405 method_not_allowed — for example a browser GET on the create-video path will never fall through to the website.
Parameter reference
POST /v1/videos — request body
| Field | Type | Required | Notes |
|---|---|---|---|
| prompt | string | yes | 1–900 characters. The brief: subject, action, setting, camera, mood. |
| aspect | "9:16" | "16:9" | yes | Vertical or landscape. |
| duration | integer | yes | Seconds. Multiple of 8, from 8 to 64. |
| resolution | string | no | 720p · 1080p · 2K · 4K. Default 1080p. |
| engine | string | no | nax-cine · nax-flow · nax-draft · nax-i2v · nax-ultra. Default nax-draft (cheapest). |
| language | string | no | Spoken language: English · Bahasa Melayu · Mandarin. |
| style | string | no | Look and grade, e.g. "warm documentary, 35mm". |
| title | string | no | Name shown in your Library. |
| hook | string | no | Opening line or on-screen hook, up to 500 characters. |
Render object — response fields
| Field | Type | Notes |
|---|---|---|
| id | string | Render id. Use it to poll and to find the item in your Library. |
| status | string | queued · rendering · completed · failed. |
| progress | integer | 0–100, rises as clips finish. |
| credits | number | Credits charged to your account for this render. |
| clips | integer | How many 8-second clips make up the render. |
| duration | integer | Finished length in seconds. |
| aspect | string | 9:16 or 16:9. |
| download_url | string | null | Signed MP4 link, present once completed. |
| poll_url | string | Relative path to poll this render. |
| error | string | null | Why a failed render stopped. |
Render lifecycle
queued ──▶ rendering ──▶ completed
│
└────────▶ failed (credits for unproduced clips are refunded)Rough timings: a single 8-second clip usually lands in 1–3 minutes; a 64-second chain can take 15–25 minutes because clips are produced in sequence for continuity. Poll every 5–10 seconds and let long jobs run — there is no cost to polling.
If your process dies mid-job, nothing is lost: call GET /v1/renders to find the render again and resume polling.
Downloads & storage
download_url is a signed link to an MP4 with sound and no watermark. Links are time-limited (a few hours) — re-poll the render to get a fresh one, and copy the file into your own storage if you need a permanent URL.
Files stay in your account Library so you can re-download later from the Studio or from GET /v1/renders. You own the commercial rights to what you generate, subject to our terms.
Credits & pricing
API renders are priced exactly like Studio renders: engine rate × length × resolution multiplier, plus a small amount for voice. Resolution multipliers are 720p ×0.8 · 1080p ×1 · 2K ×1.4 · 4K ×2.
| Example (16s, with sound) | Engine | Credits |
|---|---|---|
| Cinematic hero ad, 1080p | nax-cine | 450 |
| Everyday social clip, 1080p | nax-flow | 146 |
| Draft preview, 720p | nax-draft | 43 |
Credits are taken when the render starts, never before. Rejected requests cost nothing, failed clips are refunded automatically, and a clip that comes back shorter than billed is refunded the difference. Check the balance any time with GET /v1/credits; top up from Studio → Credits & plan.
Errors
Every error returns { "error": { "code", "message" } } with a matching HTTP status.
| Status | Code | What to do |
|---|---|---|
| 400 | invalid_request · bad_json · invalid_duration | Check the field named in the message; duration must be a multiple of 8. |
| 401 | missing_key · invalid_key | The key is absent, mistyped, rotated or revoked. Create a new one. |
| 402 | insufficient_credits | Top up, or wait for the daily free credits to reset at 08:00 MYT. |
| 403 | account_suspended | The account is suspended — contact support. |
| 403 | sub_account_not_allowed | The API is a main-account capability; ask your administrator. |
| 404 | not_found | That render id does not belong to your account. |
| 405 | method_not_allowed | Wrong HTTP method for the path. |
| 422 | content_blocked | The brief was rejected by content safety. Nothing was charged. |
| 429 | rate_limited | Too many renders in flight. Retry after the delay in the response. |
| 503 | maintenance | The feature is temporarily switched off. Retry shortly. |
Retry 429 and 503 with backoff. Never retry 400, 401 or 422 unchanged — the result will not differ.
Rate limits
Up to three renders may be in flight per account at once; a fourth returns 429. Polling is unlimited but 5–10 second intervals are plenty — anything faster just wastes your own requests.
For batch work, keep a queue on your side, run three jobs at a time, and start the next when one completes. Higher concurrency for volume pipelines is available on request.
Content safety
Every brief is screened before a single credit is spent. Sexual or adult material, and content intended to deceive, defraud, impersonate a real person without consent, or promote violence and illegal activity, is refused with 422 content_blocked and charged nothing.
If you generate a person's likeness, you must hold that person's consent. Screening runs on our servers and cannot be disabled by any request field.
Security practices
Call the API only from your server. A key in a mobile app, browser bundle or public repository can be used by anyone who finds it, and it spends your credits.
Keep keys in environment variables or a secret manager, use a separate key per app and environment, rotate with Reset if a key may have leaked, and revoke keys you no longer use. Requests must be HTTPS; plain HTTP is refused.
Your account administrator can see every key on the account with its last use, call count, credits spent and error count, and can revoke any key — or all of them — instantly.
Accounts & isolation
Keys are strictly scoped to the account that created them. A key reads only that account's renders and balance, and every charge and refund lands on that account. There is no shared pool: one team's API usage can never consume another team's credits.
Company sub-accounts use the Studio and NAX Mode, but not the API — the developer key belongs to the main account, which keeps billing and audit in one place.
FAQ
Is there a sandbox? Use nax-draft at 720p for cheap end-to-end tests — the same flow, a fraction of the credits.
Are there webhooks? Not yet; poll the render. Tell us if callbacks would help your pipeline.
Is the video watermarked? No. API output is clean at every resolution.
Can I generate images or voice over the API? Video and balance endpoints are live today; image and voice endpoints are on the roadmap — both are already available in the Studio.
Will the API change under me? The path is versioned (/v1/). New fields may be added, but existing fields will not change meaning inside a version.
Where do I get help? support@nax.com.my or the support page. Include the render id — it identifies everything we need.
Ready to build?
Create a key and your first render is a minute away — every account gets 50 free credits daily.
The signed-in reference adds copyable samples and live key management.

