Import Status
Alpha
The contract may change without notice, and imports created with it are not guaranteed to remain compatible. Not covered by the deprecation policy.
Poll the status of any design import at any phase. The API drives the initial transitions; backend processing drives PROCESSING → DONE | FAILED, so this endpoint is the only way to know when the imported template is actually ready.
Use the URL the response gives you
The exact URL is returned as links.status in the POST and PUT responses — prefer using that over constructing the URL by hand.
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string (uuid) | Yes | Import UUID returned by POST /designs/import/json. |
Response
| Field | Type | Description |
|---|---|---|
id | string (uuid) | Import UUID. |
name | string | Name supplied at creation. |
status | string | Current import status. See values below. |
created_at_ts | integer | Unix timestamp when the import was created. |
validated_at_ts | integer | null | Unix timestamp when the PUT was called. null until validation. |
next_check_after_ms | integer | null | Suggested delay before polling again, in milliseconds. null on terminal states (DONE, FAILED). |
links.dashboard | string (url) | Where to view the result. Present for a workspace template import from creation. A design import has no dashboard link until it succeeds — the design does not exist yet — and then it points at the design itself (/designs/{designId}). |
links.validate | string (url) | Only present while status is WAITING_FOR_VALIDATION. Dropped in every other state, expired imports included. |
warnings | array<object> | Structured processing decisions that didn't fail the import — e.g. font fallback, auto-fit shrink, a failed preview render. Append-only across polls. Empty when none. See Warnings & Error Codes. |
error | object | null | Structured problem entry when status is FAILED. Same shape as a single entry in the 4xx envelope ({ path, code, message, expected?, received? }). |
result | object | null | null until status == DONE. On success, describes what was created — see Result block. |
Response Example — in progress
{
"id": "1a8b2c3d-4869-11f0-96f2-0a00d9eb8f78",
"name": "Holiday Campaign",
"status": "PROCESSING",
"created_at_ts": 1749827734,
"validated_at_ts": 1749827802,
"next_check_after_ms": 2000,
"links": {
"status": "https://api.abyssale.com/designs/import/json/1a8b2c3d-4869-11f0-96f2-0a00d9eb8f78"
},
"warnings": [],
"error": null,
"result": null
}Response Example — completed with warnings
{
"id": "1a8b2c3d-4869-11f0-96f2-0a00d9eb8f78",
"name": "Holiday Campaign",
"status": "DONE",
"created_at_ts": 1749827734,
"validated_at_ts": 1749827802,
"next_check_after_ms": null,
"links": {
"status": "https://api.abyssale.com/designs/import/json/1a8b2c3d-4869-11f0-96f2-0a00d9eb8f78",
"dashboard": "https://app.abyssale.com/workspace-templates?importId=1a8b2c3d-4869-11f0-96f2-0a00d9eb8f78"
},
"warnings": [
{
"code": "font_weight_adjusted",
"path": "layers[1].properties.font_weight",
"message": "Requested weight 500 unavailable; using 400."
}
],
"error": null,
"result": {
"kind": "workspace_template",
"uuid": "9c2f31a0-8810-4c4b-bbf5-44a02e1f1d2f"
}
}Response Example — completed as design
{
"id": "1a8b2c3d-4869-11f0-96f2-0a00d9eb8f78",
"name": "Holiday Campaign",
"status": "DONE",
"next_check_after_ms": null,
"links": {
"status": "https://api.abyssale.com/designs/import/json/1a8b2c3d-4869-11f0-96f2-0a00d9eb8f78",
"dashboard": "https://app.abyssale.com/designs/9c2f31a0-8810-4c4b-bbf5-44a02e1f1d2f"
},
"warnings": [],
"error": null,
"result": {
"kind": "design",
"uuid": "9c2f31a0-8810-4c4b-bbf5-44a02e1f1d2f",
"project_uuid": "f0a9d2bc-1c1a-4f0e-9d4d-c7b8c2c8a7e1"
}
}Response Example — failed
{
"id": "1a8b2c3d-4869-11f0-96f2-0a00d9eb8f78",
"name": "Holiday Campaign",
"status": "FAILED",
"created_at_ts": 1749827734,
"validated_at_ts": 1749827802,
"next_check_after_ms": null,
"links": {
"status": "https://api.abyssale.com/designs/import/json/1a8b2c3d-4869-11f0-96f2-0a00d9eb8f78"
},
"warnings": [],
"error": {
"code": "text_fit_failed",
"path": "layers[2].properties.font_size",
"message": "Text could not fit inside the bounding box at any allowed font size."
},
"result": null
}Result block
result is null until status == DONE. On success it surfaces what was created and is polymorphic on the original target.kind:
| Field | Type | Description |
|---|---|---|
kind | enum | "design" or "workspace_template" — mirrors the request's target.kind. |
uuid | string (uuid) | UUID of the created object. For kind: "design", this is the design UUID — use it as the path parameter for GET /designs/{uuid} and GET /designs/{uuid}/as-import. |
project_uuid | string (uuid) | Only present when kind == "design". Echoes the destination project. |
Round-trip clients persist result.uuid from kind: "design" imports and feed it to GET /designs/{uuid}/as-import to get the import payload back.
Status lifecycle
An import advances through these states — the API drives the first hop, backend processing drives the rest to a terminal state:
| Status | Set by | Meaning |
|---|---|---|
WAITING_FOR_VALIDATION | POST | Import created. Upload assets and call PUT to advance. |
QUEUED | PUT (or POST when no uploads were needed) | Validation passed. Queued for backend processing. |
PROCESSING | Backend | The backend is building the template (or design) and rendering its preview thumbnails. |
DONE | Backend | Object created successfully — available in the dashboard. result is populated. |
FAILED | Backend | Backend processing failed, or the presigned upload window lapsed before the import was validated. The import will not retry. error is populated. |
These four public values are the only statuses surfaced over the wire. Any internal substate (such as preview rendering) is collapsed into PROCESSING in the response — including in the 409 message a PUT returns for an already-processed import.
PROCESSING is a projection, not a milestone
The public status is a projection of internal backend states, not a guarantee that a given state was ever observed. A fast import — or one that short-circuits because no uploads were needed — can go straight from QUEUED to DONE between two polls, and you may never see PROCESSING. Drive your logic off the terminal states (DONE / FAILED), never off having observed PROCESSING.
Abandoned imports terminate
An import you never validate does not stay pending forever. One hour after creation (the presigned upload window, expires_at_ts) the status endpoint reports it as terminally failed:
{
"status": "FAILED",
"next_check_after_ms": null,
"error": {
"path": "uploads",
"code": "missing_assets",
"message": "The presigned upload window expired before the assets were uploaded and validated. This import can no longer be validated; create a new import and upload its assets within the window."
}
}| Detail | Behavior |
|---|---|
| Which states are affected | Only WAITING_FOR_VALIDATION. A QUEUED / PROCESSING / DONE / FAILED import is never reinterpreted. |
| Boundary | Strictly now > created_at_ts + 3600 — the boundary second is not expired. |
links.validate | Absent. It is only present while an import is genuinely WAITING_FOR_VALIDATION. |
PUT on an expired import | 422 with code missing_assets and the same message — identical to the never-uploaded case, so no new client branch is needed. |
A compliant poller therefore always terminates: either at DONE / FAILED from processing, or at FAILED when the upload window lapses.
Previews render during PROCESSING
Thumbnails are generated automatically for every import — the payload never carries a preview image. PROCESSING may last several seconds while one preview per format is rendered; the status flips to DONE automatically once they are ready — no extra polling endpoint is required. A failed preview render never fails the import: the design is still created and the import ends DONE with a preview_generation_failed warning (the thumbnail may be missing).
Polling
Use next_check_after_ms to schedule your next poll. It is populated while status is WAITING_FOR_VALIDATION, QUEUED, or PROCESSING, and null once the import reaches DONE or FAILED. Stop polling on terminal states.
Example
curl "$STATUS_URL" \
-H "x-api-key: $API_KEY"$STATUS_URL is the links.status value from the POST or PUT response.
Scope
Results are always scoped to the company associated with your API key. Polling an import that belongs to a different company returns 404 Not Found.
List your imports
Lists your JSON imports, newest first.
Recovering a lost import ID
The import flow is POST → upload → PUT. If your client crashes or times out between those steps, the import already exists but you no longer hold its ID — it cannot be resumed, cancelled or polled. This endpoint is how you find it again: list, read the id, then continue with the normal validate or status call.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | WAITING_FOR_VALIDATION, QUEUED, PROCESSING, DONE or FAILED. Any other value is rejected with unknown_enum_value. |
created_after | integer | No | Unix timestamp (seconds). Imports created at or after this moment. |
created_before | integer | No | Unix timestamp (seconds). Imports created at or before this moment. |
limit | integer | No | 1–200, default 50. |
status filters on the effective status, exactly as the single-import endpoint reports it — so an import whose upload window has expired is matched by ?status=FAILED, not by ?status=WAITING_FOR_VALIDATION, even though its stored row is untouched. That is what makes abandoned imports findable:
GET /designs/import/json?status=FAILEDFor "everything from the last month", pass a created_after timestamp.
Response
An array of summaries. warnings[] and the error object are not included — they are unbounded, so a row carries warning_count and a links.status URL to fetch the full record from.
| Field | Type | Description |
|---|---|---|
id | string (uuid) | Import UUID. |
name | string | Name supplied at creation. |
status | string | Effective status (see above). |
created_at_ts | integer | Unix timestamp of creation. |
validated_at_ts | integer | null | When the PUT queued it, or null if never validated. |
warning_count | integer | Number of warnings so far. |
links | object | Always carries status. validate appears only while WAITING_FOR_VALIDATION, and dashboard only when there is somewhere to point — see links.dashboard above. |
result | object | null | What the import produced. Present only once status is DONE. |
[
{
"id": "64238d01-d402-474b-8c2d-fbc957e9d290",
"name": "Autumn card",
"status": "FAILED",
"created_at_ts": 1649942114,
"validated_at_ts": null,
"warning_count": 0,
"links": {
"status": "https://api.abyssale.com/designs/import/json/64238d01-d402-474b-8c2d-fbc957e9d290"
},
"result": null
}
]No pagination
There is no cursor. Results are capped by limit, so a company with more imports than the cap cannot reach the oldest ones directly — narrow the window with created_before / created_after to walk further back.
This endpoint lists JSON imports only.
Error codes
The full catalog of warning codes, error codes, and the three response-envelope shapes now lives on its own page — see Warnings & Error Codes.
