# Quady3D API guide and reference

> Use authenticated text-to-3D and image-to-3D jobs, recover interrupted work and download the actual result files.

API base path: /api/v1. Contract revision: 0.1.0-dev. Client archives: 0.1.2.
[Documentation index](/llms.txt) · [Client examples](/developers/docs/clients.md) · [OpenAPI JSON](/api/v1/openapi)

## Authentication

Use a dedicated Quady3D API Key with only the scopes your workflow needs. Get or manage a Key in [Connected apps](/account?section=connections). Keep the Key in a trusted local or server environment; never include it in a URL, browser bundle, shared project or log.

```http
GET /api/v1/account HTTP/1.1
Authorization: Bearer <YOUR_QUADY3D_API_KEY>
Accept: application/json
```

## Generation workflow

1. **Check the connection.** Read the account balance, download access and Key limits. Discover an available model and its parameter schema for your chosen input.
2. **Get a quote.** Quote the exact operation, model, inputs and parameters. Quotes do not reserve generation credits. Check the quoted cost against the user's approved budget.
3. **Save, then submit.** Before POST /jobs, save the exact request body and a unique Idempotency-Key. Submit with quote_id and max_credits. Keep the returned job ID.
4. **Resume the same task.** Poll GET /jobs/{id} until succeeded or failed. A timeout or submission_unknown needs recovery of the original request, without creating a replacement task.
5. **Save the actual file.** Use an asset's download_path from the completed job. Stream to a temporary file, validate the actual file and publish to the approved destination without overwriting an existing file.

For image input, POST a single raw PNG, JPEG or WebP to /uploads (up to 8388608 bytes). Reuse its upload ID before expires_at. Do not use multipart, base64 or a remote image URL. Discover parameter names and bounds with GET /models; file formats depend on the model and completed result.

Bind saved work to its API address and account_id. If the create-job response is lost, replay the original body and Idempotency-Key, or query the known job ID. Accepted replay returns the original task even after its quote/input expires. Do not silently requote or issue a new key while acceptance is unresolved. The user must approve a separate generation action.

## Job states

- **submitting**: Submission is being processed. Keep the job and wait.
- **submission_unknown**: Submission is unresolved. Query the original job; do not create a replacement.
- **queued**: The job is accepted and waiting. Continue checking the same job.
- **processing**: Generation is running. Continue checking the same job.
- **succeeded**: Read the actual assets, formats and download paths before saving files.
- **failed**: Read the job error and actual charged/refunded amounts. A new generation is a separate user action.

## Endpoints

### GET /api/v1/models

List public model capabilities. 
Authentication: Bearer Key. Required scopes: models:read.

Parameters:

- operation (query, text-to-3d | image-to-3d, optional). 

Responses:

- 200: Available models, input limits and parameter names. Schema: ModelList.
- 400: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 401: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 402: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 403: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 404: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 409: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 410: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 413: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 415: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 429: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 503: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.

### GET /api/v1/account

Read balance, rights and Key limits. 
Authentication: Bearer Key. Required scopes: account:read.

Responses:

- 200: Public credit balance and existing account rights. Schema: Account.
- 400: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 401: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 402: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 403: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 404: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 409: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 410: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 413: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 415: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 429: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 503: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.

### POST /api/v1/uploads

Stage a selected input without a generation charge. Send a single raw PNG, JPG or WebP body, up to 8 MiB. No multipart wrapper, base64 or remote URL. When advanced operations are enabled, embedded GLB 2.0 models up to 50 MiB are also accepted as model/gltf-binary. Model dependencies must be embedded, with no URI references. Use source_upload_id for model processing. The immutable owned upload can be reused until expires_at; active task references protect its bytes after expiry.
Authentication: Bearer Key. Required scopes: uploads:write.

Request Content-Type: image/png, image/jpeg, image/webp. Maximum: 8388608 bytes.

Responses:

- 201: An owned upload ID and its expiry, not an object key. Schema: UploadedImage.
- 400: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 401: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 402: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 403: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 404: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 409: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 410: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 413: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 415: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 429: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 503: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.

### POST /api/v1/quotes

Quote normalized model inputs. 
Authentication: Bearer Key. Required scopes: jobs:write.

Request Content-Type: application/json.

text-to-3d:

| Field | Type | Required | Details |
| --- | --- | --- | --- |
| operation | "text-to-3d" | Yes |  |
| model | tripo-h3-1 \| rodin-2-5-fast \| hunyuan-3-1-rapid \| hunyuan-3 \| hunyuan-3-1-pro \| rodin-2-5 \| tripo-p2 \| meshy-7-1 \| gpt-6-astra | Yes |  |
| inputs | object | Yes |  |
| inputs.prompt | string | Yes | Minimum length: 1. Maximum length: 1000. |
| parameters | object | No | Model-specific parameter names are listed by GET /models. Values follow that model's supported bounds. |

image-to-3d:

| Field | Type | Required | Details |
| --- | --- | --- | --- |
| operation | "image-to-3d" | Yes |  |
| model | tripo-h3-1 \| hunyuan-2-mini \| rodin-2-5-fast \| trellis-2 \| pixal3d \| hunyuan-3-1-rapid \| hunyuan-3 \| seed3d-2 \| hunyuan-3-1-pro \| rodin-2-5 \| tripo-p2 \| meshy-7-1 \| hi3d-3 \| gpt-6-astra | Yes |  |
| inputs | object | Yes |  |
| inputs.upload_ids | string[] | Yes | Minimum items: 1. Maximum items: 1. |
| parameters | object | No | Model-specific parameter names are listed by GET /models. Values follow that model's supported bounds. |

Responses:

- 201: A five-minute quote; no credits reserved. Schema: Quote.
- 400: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 401: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 402: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 403: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 404: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 409: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 410: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 413: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 415: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 429: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 503: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.

### POST /api/v1/jobs

Create or recover an idempotent generation. Persist a unique action ID before sending. Reuse the exact body and Idempotency-Key on retry. An accepted replay survives quote/input expiry and returns the original job. Account balance, concurrency and Key budgets are checked together before a provider submission.
Authentication: Bearer Key. Required scopes: jobs:write.

Parameters:

- Idempotency-Key (header, string, required). Minimum length: 1. Maximum length: 128. Pattern: ^[!-~]+$

Request Content-Type: application/json.

text-to-3d:

| Field | Type | Required | Details |
| --- | --- | --- | --- |
| operation | "text-to-3d" | Yes |  |
| model | tripo-h3-1 \| rodin-2-5-fast \| hunyuan-3-1-rapid \| hunyuan-3 \| hunyuan-3-1-pro \| rodin-2-5 \| tripo-p2 \| meshy-7-1 \| gpt-6-astra | Yes |  |
| inputs | object | Yes |  |
| inputs.prompt | string | Yes | Minimum length: 1. Maximum length: 1000. |
| parameters | object | No | Model-specific parameter names are listed by GET /models. Values follow that model's supported bounds. |
| quote_id | string | Yes | Pattern: ^quo_[a-f0-9]{32}$ |
| max_credits | number | Yes | Greater than 0. Maximum: 1000000. |

image-to-3d:

| Field | Type | Required | Details |
| --- | --- | --- | --- |
| operation | "image-to-3d" | Yes |  |
| model | tripo-h3-1 \| hunyuan-2-mini \| rodin-2-5-fast \| trellis-2 \| pixal3d \| hunyuan-3-1-rapid \| hunyuan-3 \| seed3d-2 \| hunyuan-3-1-pro \| rodin-2-5 \| tripo-p2 \| meshy-7-1 \| hi3d-3 \| gpt-6-astra | Yes |  |
| inputs | object | Yes |  |
| inputs.upload_ids | string[] | Yes | Minimum items: 1. Maximum items: 1. |
| parameters | object | No | Model-specific parameter names are listed by GET /models. Values follow that model's supported bounds. |
| quote_id | string | Yes | Pattern: ^quo_[a-f0-9]{32}$ |
| max_credits | number | Yes | Greater than 0. Maximum: 1000000. |

Responses:

- 202: A durable job. Immediate definitive rejection is represented as a failed job with its actual refund. Schema: Job.
- 400: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 401: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 402: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 403: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 404: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 409: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 410: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 413: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 415: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 429: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 503: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.

### GET /api/v1/jobs

List owned API tasks. 
Authentication: Bearer Key. Required scopes: jobs:read.

Parameters:

- limit (query, integer, optional). Minimum: 1. Maximum: 100. Default: 20.
- cursor (query, string, optional). Pattern: ^[0-9]{1,12}:int_[a-f0-9]{64}$
- status (query, submitting | submission_unknown | queued | processing | succeeded | failed, optional). 

Responses:

- 200: Newest tasks first with a stable cursor. Schema: JobList.
- 400: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 401: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 402: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 403: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 404: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 409: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 410: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 413: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 415: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 429: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 503: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.

### GET /api/v1/jobs/{id}

Query and reconcile the same owned task. A transient provider error is not proof of failure. submission_unknown remains recoverable and must not be replaced by a new creation.
Authentication: Bearer Key. Required scopes: jobs:read.

Parameters:

- id (path, string, required). Pattern: ^int_[a-f0-9]{64}$

Responses:

- 200: The durable public task state, credit amounts and actual assets. Schema: Job.
- 400: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 401: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 402: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 403: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 404: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 409: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 410: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 413: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 415: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 429: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 503: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.

### GET /api/v1/assets/{id}

Download an owned asset. Ownership, retention and download rights are checked before file delivery. Save into an authorized temporary file, validate it, then publish without overwriting an existing file.
Authentication: Bearer Key. Required scopes: assets:read.

Parameters:

- id (path, string, required). Pattern: ^[a-zA-Z0-9_-]+$

Responses:

- 200: Streamed binary file with its actual Content-Type and attachment filename.
- 206: Partial file for a valid byte range.
- 304: Unmodified owned file after current access checks.
- 400: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 401: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 402: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 403: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 404: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 409: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 410: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 412: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 413: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 415: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 416: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 429: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 503: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.

### GET /api/v1/openapi

Read the API contract. 
Authentication: public. 

Responses:

- 200: Machine-readable OpenAPI document, available when API access is enabled.
- 400: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 429: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.
- 503: A stable error. Retry writes only with the original Idempotency-Key and body. Schema: ErrorResponse.

## Response fields

### Account

| Field | Type | Required | Details |
| --- | --- | --- | --- |
| account_id | string | Yes | Stable account comparison value across Keys from the same API. Not a credential; bind local recovery to both API address and account_id. Pattern: ^acc_[a-f0-9]{64}$ |
| balance_credits | number | Yes | Public credits, already converted from ledger units. Minimum: 0. |
| plan | string | Yes |  |
| download_access | boolean | Yes |  |
| key_limits | object | Yes |  |
| key_limits.max_job_credits | integer | Yes | Minimum: 0. |
| key_limits.daily_credits | integer | Yes | Minimum: 0. |
| request_id | string | Yes |  |

### ModelList

| Field | Type | Required | Details |
| --- | --- | --- | --- |
| data | object[] | Yes |  |
| generation_operations | text-to-3d \| image-to-3d[] | Yes |  |
| request_id | string | Yes |  |

### Model

| Field | Type | Required | Details |
| --- | --- | --- | --- |
| id | string | Yes |  |
| name | string | Yes |  |
| maker | string | Yes |  |
| operation | text-to-3d \| image-to-3d | Yes |  |
| available | boolean | Yes |  |
| unavailable_reason | string \| null | Yes |  |
| estimated_credits | number \| null | Yes | Minimum: 0. |
| parameter_names | string[] | Yes |  |
| parameter_schema | object | Yes | Version 1 JSON Schema subset: typed properties, defaults, bounds, enums, and conditional allOf limits. x- annotations describe controls; admission remains server-validated. |
| input | object | Yes |  |
| capabilities | object | Yes |  |

### UploadedImage

| Field | Type | Required | Details |
| --- | --- | --- | --- |
| id | string | Yes | Pattern: ^upl_[a-f0-9]{32}$ |
| content_type | image/png \| image/jpeg \| image/webp | Yes |  |
| byte_size | integer | Yes | Minimum: 1. Maximum: 8388608. |
| sha256 | string | Yes | Pattern: ^[a-f0-9]{64}$ |
| expires_at | integer | Yes | Minimum: 0. |
| request_id | string | Yes |  |

### Quote

| Field | Type | Required | Details |
| --- | --- | --- | --- |
| id | string | Yes | Pattern: ^quo_[a-f0-9]{32}$ |
| operation | text-to-3d \| image-to-3d | Yes |  |
| model | string | Yes |  |
| credits | number | Yes | Public credits, already converted from ledger units. Minimum: 0. |
| price_version | string | Yes |  |
| expires_at | integer | Yes | Minimum: 0. |
| download_access | boolean | Yes |  |
| request_id | string | Yes |  |

### Job

| Field | Type | Required | Details |
| --- | --- | --- | --- |
| id | string | Yes | Pattern: ^int_[a-f0-9]{64}$ |
| operation | text-to-3d \| image-to-3d | Yes |  |
| model | string | Yes |  |
| status | submitting \| submission_unknown \| queued \| processing \| succeeded \| failed | Yes |  |
| stage | string | No |  |
| credits | object | Yes |  |
| credits.reserved | number | Yes | Public credits, already converted from ledger units. Minimum: 0. |
| credits.charged | number | Yes | Public credits, already converted from ledger units. Minimum: 0. |
| credits.refunded | number | Yes | Public credits, already converted from ledger units. Minimum: 0. |
| assets | object[] | Yes |  |
| created_at | integer | Yes | Minimum: 0. |
| expires_at | integer \| null | No | Minimum: 0. |
| files_expired | boolean | No |  |
| error | object | No |  |
| error.code | string | No |  |
| error.message | string | No |  |
| request_id | string | Yes |  |

### Asset

| Field | Type | Required | Details |
| --- | --- | --- | --- |
| id | string | Yes |  |
| format | string | Yes |  |
| role | string \| null | Yes |  |
| content_type | string | Yes |  |
| byte_size | integer \| null | Yes | Minimum: 0. |
| download_path | string | Yes | Pattern: ^/api/v1/assets/[a-zA-Z0-9_-]+$ |

### JobList

| Field | Type | Required | Details |
| --- | --- | --- | --- |
| data | object[] | Yes |  |
| next_cursor | string \| null | Yes |  |
| request_id | string | Yes |  |

### ErrorResponse

| Field | Type | Required | Details |
| --- | --- | --- | --- |
| error | object | Yes |  |
| error.code | string | Yes |  |
| error.message | string | Yes |  |
| error.request_id | string | Yes |  |
| error.retryable | boolean | Yes |  |

## Handling errors

Errors contain error.code, error.message, error.request_id and error.retryable. Keep the request ID when asking for support. Respect Retry-After. A retryable error does not authorize a new generation or an increased credit limit.

- **400**: Correct the request fields using the model and endpoint schemas.
- **401 / 403**: Check the Key, account, required scopes and download access. Keep credentials out of URLs and client-side code.
- **402**: Check the account balance and credit limits. Obtain approval before increasing a budget.
- **404 / 410**: Check the owned resource ID, connection and expiry. An unavailable download does not authorize another generation.
- **409**: Read error.code. An idempotency conflict requires the original saved request. Only refresh an expired quote for a request confirmed unaccepted; do not replace an unresolved submission.
- **413 / 415**: Use a supported raw image and stay within the upload byte limit.
- **429 / 503**: Honor Retry-After when present. Recover writes with the same Idempotency-Key and body; avoid rapid retry loops.
- **412 / 416**: Review download preconditions or the requested byte range before trying the same asset again.

## File delivery

Read assets only from a succeeded job. Select the actual available format and download_path. Access checks include ownership, retention and download rights. Interrupted downloads recover the same asset. Stream to a temporary file, validate the actual bytes, then publish without replacing an existing file. Keep the job ID for later recovery. Full SDK examples include this file workflow in [Client examples](/developers/docs/clients.md).
