API

Haze Method / Developers

Haze Engine API

Run Haze Classic and Haze Lite inside your own site, Discord bot or app, so the videos your users post to TikTok keep their quality. Your server sends a video's header, gets a plan back, and builds the optimized file from its own copy of the video.

Version: v1 · Last updated: October 18, 2026

How it works

An MP4 is a few small header boxes (ftyp, moov, …) plus one big mdat box with the actual video and audio. Haze's engines only change the header. So the API never needs your video:

  1. 1
    Prepare

    Read the top-level boxes and copy every box except mdat. That's usually a few hundred KB.

  2. 2
    Ask for a plan

    Your server sends the header to POST /v1/patch with your API key. Haze runs the engine and answers with a plan.

  3. 3
    Assemble

    Build the output from the plan: new header bytes plus byte ranges of your own file. The result is ready to post on TikTok.

The client library does all three steps for you. It's one file with no dependencies, and its output is byte-for-byte what tikhaze.com produces.

Which engine?

The API runs Haze Classic (engine 5.5, the default) and Haze Lite (engine lite). Both take H.264 or HEVC; Lite also needs an AAC audio track. TikTok plays Lite videos at up to 720p 60fps. A phone's gallery may show a file from either engine as 0:00 or play only its sound: the file is fine and plays in full on TikTok. Each costs one run. Haze Max needs extra audio preparation on the device and isn't on the API yet.

When the Haze team marks an engine Patched or Fixing, the API refuses it for free until it works again; GET /v1/engines always shows the live status.

Pricing and your keys

API pack

$100one time

  • 100,000 engine runs, one per video
  • Runs never expire. Buy again any time to add more.
  • Refused videos and repeat requests are free
  • Up to 5 keys, revocable any time

The API rules apply too.

Paid through Whop with card, Apple Pay or Google Pay. Your runs show up below a few seconds after payment.

Your keys

Sign in with your Haze account to buy a pack and manage your keys.

Build it with AI

Using an AI coding tool? Copy the prompt for yours and paste it in your project. It tells the AI how the client library works, where the key goes, which errors to handle and how to test without spending runs, and the AI fits it to your site, bot or app.

The prompts never contain your key. Create one above and put it in HAZE_API_KEY yourself. Read what the AI changes before you ship it.

Quick start (Node)

  1. Buy a pack and create a key above. Put it in an environment variable, never in your code: HAZE_API_KEY=hz_live_…
  2. Download the client next to your code: haze-engine-api.mjs
  3. Optimize a video. Node 20 or newer:
import { openAsBlob } from 'node:fs';
import { writeFile } from 'node:fs/promises';
import { randomUUID } from 'node:crypto';
import { optimize } from './haze-engine-api.mjs';

const file = await openAsBlob('input.mp4');
const result = await optimize(file, {
  apiKey: process.env.HAZE_API_KEY,
  requestId: randomUUID(), // one id per video; reuse it to retry for free
  // engine: 'lite',        // Haze Lite instead of the default Haze Classic
});
await writeFile('input_haze.mp4', Buffer.from(await result.blob.arrayBuffer()));
console.log(`Done with ${result.engine}. ${result.runsLeft} runs left.`);

Post input_haze.mp4 as it is. Don't re-encode or edit it afterwards, or the optimization is lost. Posting on tiktok.com or through TikTok's Content Posting API works; the TikTok phone app re-encodes uploads.

Websites and apps

Your key must stay on your server, and the API doesn't answer browsers on other sites. In a website or app, let the browser do the heavy part and pass only the header through your server:

In the browser

import { prepare, assemble } from './haze-engine-api.mjs';

async function optimizeInBrowser(file) {
  const prepared = await prepare(file); // reads the header only
  const res = await fetch('/api/haze-optimize', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      requestId: crypto.randomUUID(),
      layout: prepared.layout,
      header: prepared.header,
    }),
  });
  const data = await res.json();
  if (!res.ok) throw new Error(data.error);
  return assemble(file, data.plan, prepared); // a Blob, ready to download or upload
}

On your server (Express)

import express from 'express';

const app = express();
// The header can be up to 16 MB, base64-encoded in JSON.
app.post('/api/haze-optimize', express.json({ limit: '24mb' }), async (req, res) => {
  // Check your own user here: who may spend your runs?
  const { requestId, layout, header } = req.body;
  const upstream = await fetch('https://api.hazemethod.xyz/v1/patch', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.HAZE_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ requestId, layout, header }),
  });
  res.status(upstream.status).json(await upstream.json());
});

Any language works on the server: it only forwards JSON. Limit who can call your endpoint, because every plan it gets back spends one of your runs.

API reference

Base URL https://api.hazemethod.xyz. Every request carries your key:

Authorization: Bearer hz_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Answers are JSON. Limits per key: 120 requests a minute and 4 /v1/patch requests at the same time (more answer 503 with Retry-After).

POST /v1/patch

Runs an engine on a video's header and returns the plan. A plan costs one run. The same requestId with the same header within an hour is answered again for free, so retry with the same id when an answer gets lost.

FieldTypeDescription
requestIdstring8–80 characters: A–Z a–z 0–9 _ -. One per video. A UUID works.
enginestring, optionalAn id from /v1/engines. Leave it out for the default (the first working engine).
layout.fileSizeintegerThe size of the whole file in bytes.
layout.boxesarrayEvery top-level box in order: { type, start, size, header }, where header is 8, or 16 for a 64-bit size. At most 64 boxes; exactly one moov and one mdat, ftyp first, no moof.
headerstringBase64 of every box except mdat, concatenated in file order. At most 16 MB before encoding.

Answer 200:

{
  "requestId": "6f1c…",
  "engine": "5.5",
  "plan": {
    "engine": "5.5",
    "size": 106285,
    "parts": [
      { "b": "AAAAHGZ0eXBpc29t…" },   // literal bytes, base64
      { "src": [1460, 104831] },      // bytes [start, end) of your own file
      { "fill": "00", "n": 16 }       // a hex unit repeated n times
    ]
  },
  "runsLeft": 9999,
  "replay": false
}

Concatenate the parts in order. A src range always lies inside your file's mdat data, and the total length equals plan.size.

GET /v1/engines

The engines your key can run, with their live status (working, patched or fixing, and an optional note). Free.

{
  "default": "5.5",
  "engines": [
    { "id": "5.5", "name": "Haze Classic", "status": "working" },
    { "id": "lite", "name": "Haze Lite", "status": "working" }
  ]
}

GET /v1/usage

Your balance and recent use. Free.

{ "runsLeft": 9998, "runsUsed": 2, "last24h": 2, "last30d": 2 }

Errors

Errors answer { "error": "code" }. Nothing is charged for any of them.

StatusCodeWhat to do
400invalid_request_id, unknown_engine, engine_not_offeredFix the request.
401missing_key, invalid_keySend Authorization: Bearer … with a live key.
402no_runs_leftBuy another pack.
403customer_suspendedYour access is on hold. Email support@tikhaze.com.
409request_id_usedThat id already bought a different video, or more than an hour ago. Use a new id.
409engine_unavailable, method_patchedThe engine is Patched or Fixing. Try again later; check /v1/engines.
422unsupported_layout, unsupported_codec, already_patched, header_too_largeThe video can't be optimized as it is: fragmented MP4, more than one mdat, not H.264/HEVC, or already optimized with Haze.
422resolution_too_high, fps_too_high, invalid_resolution, invalid_fps, invalid_file_sizeBeyond Haze's limits (up to 4K and 120 fps).
429rate_limitedSlow down; the limit is per minute.
500recipe_failedAsk again with the same requestId. The Haze team is alerted.
503api_paused, maintenanceTry again in a few minutes.

Client library

One JavaScript module, no dependencies, MIT licence. It runs in Node 18+ and in modern browsers.

FunctionWhereWhat it does
prepare(file)browser or serverReads the header boxes. Returns { layout, header, payloadStart, payloadEnd }.
requestPlan({ apiKey, requestId, prepared, engine? })serverCalls POST /v1/patch. Throws HazeApiError with code and status.
assemble(file, plan, prepared)browser or serverChecks the plan and builds the output Blob.
optimize(file, { apiKey, requestId, engine? })serverAll three, with one free retry. Returns { blob, engine, runsLeft, replay }.

Not using JavaScript? Port prepare and assemble: they're about 100 lines and the format above is all they use.

Rules

A summary. The full rules are in the Terms of Service, Section 8 (Developer API); packs and refunds follow the Refund Policy, and the Privacy Policy (section 5a) explains what Haze processes.

  • Keep your keys secret. Use them only on servers you control. Anyone with your key can spend your runs; revoke a leaked key at once.
  • Don't resell or share access. You may build products for your own users on top of the API. You may not sell, share or hand out keys, or offer a proxy whose purpose is to give others raw access to the API.
  • No abuse. No attempts to get around limits, charges or the header-only design, and no use that breaks TikTok's rules or the law.
  • Engines change. TikTok changes its systems, so an engine can stop working, be paused or be replaced at any time. Refused requests are never charged, and your unused runs stay on your account.
  • Suspension. Haze may revoke keys or suspend access for a breach of these rules or a chargeback. A refunded pack's runs are removed.
  • Privacy. If your users' videos go through the API, tell them that the video's header (not the video itself) is processed by Haze.

FAQ

What counts as a run?

One video that came back with a plan. Refusals, errors and repeat answers for the same requestId and header within an hour are free.

Does Haze see my users' videos?

No. Only the header boxes (track tables, timing, codec settings, metadata) are sent. The video and audio data stay with you.

Can I call the API straight from a browser?

No. Your key would be visible to anyone, and the API doesn't answer other sites' pages. Use your own server in between.

Which engines can I use?

Haze Classic (the default) and Haze Lite: send "engine": "lite" to use Lite. Both cost one run. Haze Max isn't on the API yet, because it needs audio preparation on the device.

Where do I get help?

Email support@tikhaze.com with your key's first 12 characters (never the whole key) and the requestId.