Authentication and conventions
Requests and responses
- The application layer does not restrict HTTP or HTTPS. In production, strongly prefer enforcing HTTPS at the gateway so API Keys never travel over the network in plaintext.
- Requests and responses use UTF-8 JSON.
- POST requests must include
Content-Type: application/json. - Field names use lower camel case.
appId,projectId, andrunIdare string values representing an App ID, Project ID, and Run ID. Store and return them unchanged; do not generate them yourself.- All prices are denominated in Credits and represented as strings with exactly 8 decimal places, for example
"12.50000000". Do not parse them as JSON floating-point numbers. - Progress is an integer from
0to100. Determine success fromstatus, not from progress alone. - Every successful response uses
{ "code": 200, "message": "success", "data": ... }, with business data underdata. - The response body's
codeis a protocol field currently fixed at200. It is separate from the HTTP 201 status returned after successful creation.
Authentication
Every request must include exactly one Authorization header:
Authorization: Bearer <API_KEY>
An API Key only authenticates a user's access to OpenAPI. It is not bound to an App, organization, or wallet. Each user has one API account, and all Keys created by that user share projects, Runs, and account-level rate limits.
The projectId supplied when creating a Run determines ownership of its results and charges. Replacing or revoking a Key does not change project ownership.
Revoking a Key immediately prevents it from making new requests, but does not delete existing projects, Runs, or billing records. Other active Keys under the same account can still query those resources.
Request tracing
Every response includes:
X-Request-Id: req_...
Clients may also send their own X-Request-Id. It must contain 1–80 letters, numbers, periods, underscores, colons, or hyphens. The server generates a replacement when the supplied value is invalid.
When troubleshooting, provide the X-Request-Id, but never provide the complete API Key.
Creation requests and duplicate submissions
v1 creation APIs do not accept an idempotency parameter. Every POST /projects creates a project, and every POST /app-runs creates a Run and records the Key used for that Run.
If a network timeout occurs or no response arrives, do not automatically resubmit a creation request. First check the project list or a saved runId. If the result cannot be confirmed, another POST may create a duplicate resource and incur a new charge.
Error protocol
Application-level errors return HTTP 200.
Application error response example
200success indicates an application-level failureClients must first test whether the top-level message equals success. Any other value means the API call failed; use data.error.code to identify the reason. Do not treat HTTP 200 or the top-level code=200 as business success. data.error.message is intended for debugging and human readers, not program branches.
Recommended check:
const response = await fetch(url, options);
const body = await response.json();
if (body.message !== "success") {
throw new AppRunApiError(
body.data.error.code,
body.data.error.message,
body.data.requestId,
);
}
return body.data;
Only successful creation responses use HTTP 201. Successful queries and all application-level errors use HTTP 200. Network, TLS, proxy, and non-JSON response errors are outside this application protocol and must be handled separately.
Rate limits
Default account-level limits:
- Creation requests: 30 per minute.
- Query requests: 300 per minute.
All Keys under the same account share these quotas. When a limit is exceeded, data.error.code is RATE_LIMITED and the response includes a Retry-After header. Wait for the number of seconds specified by the header before retrying, and add random jitter so concurrent requests do not all resume at once.