Skip to content
English

Introduction

/v1/tasks is the single entry point for all async generation models — image, video, and audio. Whatever the model, you submit, poll, and receive terminal callbacks through the same set of endpoints: submitting returns a taskId, then you poll the task detail or wait for a callback to get the final output.

All requests use the same Base URL:

https://api.hiapi.ai
MethodPathPurpose
POST/v1/tasksCreate a task, returns taskId
GET/v1/tasksList tasks (paginated, newest first)
GET/v1/tasks/:idGet task detail: status, output, or failure reason

Every request carries the account API key in the Authorization header:

Authorization Bearer YOUR_API_KEY required

Account API key. Required on every request.

Content-Type application/json required

The request body is JSON.

A task must belong to the API key’s account; cross-account queries return 404.

Set the HiAPI model name via model, and put business parameters in the input object. The fields of input are defined per model — see the relevant model page.

Async tasks support two ways to get results:

  1. Polling — after creating a task, request GET /v1/tasks/:id at intervals until status is terminal.
  2. Callback (Webhook) — provide callback.url when creating the task, and HiAPI POSTs to that URL when the task reaches a terminal state (success or fail).

The callback request:

  • Method POST, Content-Type application/json
  • Body is identical to the data field of GET /v1/tasks/:id (the task detail object)
  • callback.when currently supports only final (both success and fail fire a callback)

Set a “Webhook signing key” on the account settings page in the HiAPI console (shared secret, 16–256 chars; empty means no signing).

  • Not set: callback requests carry no signature header.
  • Set: each callback carries
    • X-HiAPI-Timestamp: Unix seconds (string)
    • X-HiAPI-Signature: hex( HMAC_SHA256(secret, timestamp + "." + body) )

Receiver verification (Python pseudocode):

import hmac, hashlib
ts = request.headers["X-HiAPI-Timestamp"]
sig = request.headers["X-HiAPI-Signature"]
body = request.raw_body # raw bytes, not JSON-parsed
expected = hmac.new(
secret.encode(),
(ts + "." + body).encode(),
hashlib.sha256,
).hexdigest()
assert hmac.compare_digest(expected, sig), "bad signature"
# Recommended: reject requests where abs(now - int(ts)) > 5 minutes (replay protection)
ItemBehavior
EnqueueOnce, when the task reaches success or fail
SuccessReceiver returns HTTP 2xx
RetryNon-2xx / timeout / network error retries at immediately → +1 min → +5 min → +20 min, up to 4 attempts
TerminalAfter 4 failed attempts no more retries; does not affect the task’s own state

Terminal callbacks are delivered “at least once”, not “exactly once”. Deduplicate by taskId on your side.

statusMeaningReturns output?
queuedEnqueued, not startedNo
handlingProcessingNo
archivingDone, output being preparedNo
successTerminal: complete, output availableYes
failTerminal: failedNo, returns error

The only terminal states are success / fail; they never convert to each other, and a taskId’s result is fixed once terminal.

StatusMeaning
200Success (task detail returns 200 even when status=fail; the failure is in the body’s error)
400Invalid request — see error_code below
404Task does not exist or does not belong to the current account
503Platform temporarily unavailable; retry later with exponential backoff

The synchronous failure response of POST /v1/tasks (error_code) and a terminal task’s error.code share this enum:

codeMeaningWhat to do
INVALID_REQUESTInvalid body (missing field / wrong type / bad callback.url / model rejects the input)Fix the request; do not retry the same request
MODEL_UNAVAILABLEModel unavailable (disabled, no permission, temporarily unavailable)Retry shortly, or switch models
TASK_FAILEDTask failedRetry once; contact support if persistent
TASK_TIMEOUTTask timed outRetryable
STORAGE_UNAVAILABLEOutput storage errorRetryable; contact support if persistent

Failure responses look like:

{
"code": 400,
"message": "invalid request",
"data": null,
"error_code": "INVALID_REQUEST"
}
POST /v1/tasks ──► queued ──► handling ──► archiving ──► success (terminal)
(200 / taskId) │ │
▼ ▼
fail fail (terminal)
success / fail triggers the callback (if callback.url was set)