Submit a product for review
Uploads a design file and creates a private product from it. 3DAPI then reviews the design, which a person does, so do not poll for it: wait for the product.approved or product.rejected webhook (or check review.status later), then run publish_product.
Variants, images and attachments can be sent in the same create_product call; this workflow keeps the minimum.
What you need
- namestringRequired
Product name.
- file_namestringRequired
Name of the design file, for example
tracker.3mf. - content_typestringRequired
MIME type of the design file:
model/3mf,model/stl,model/objorapplication/octet-stream. - size_bytesintegerRequired
Size of the design file in bytes, up to 150 MB.
- materialsarray of stringRequired
Catalog material ids (
mat_...) the design may be printed in.list_materialslists them. - idempotency_keystring
A unique string for this attempt, for example a UUID. Send the same value when you retry, so the write happens once.
Step 1: Start a file upload
Reserve an upload for the design file. Then send the file bytes to upload_url with the returned method and headers. That transfer goes straight to storage, not to this API, so it is not a step here; do it before the next step.
{
"purpose": "design_file",
"file_name": "$inputs.file_name",
"content_type": "$inputs.content_type",
"size_bytes": "$inputs.size_bytes"
}Succeeds when:
$statusCode == 201
Keeps for the next steps:
upload_id:$response.body#/idupload_url:$response.body#/upload_urlmethod:$response.body#/methodheaders:$response.body#/headers
Step 2: Create a product
Create the private product with the uploaded file as its design. It starts with review.status: pending. A full plan is refused with plan_limit_reached, whose details.fix_url opens the upgrade page; a file that never reached upload_url is refused with upload_missing.
{
"header Idempotency-Key": "$inputs.idempotency_key"
}{
"name": "$inputs.name",
"designs": [
{
"key": "main",
"file": {
"upload": "$steps.upload_design.outputs.upload_id"
},
"materials": {
"mode": "single",
"allowed": "$inputs.materials"
}
}
]
}Succeeds when:
$statusCode == 201
Otherwise:
retry_server_error: retry after 5 seconds, at most 3 times, when$statusCode >= 500.plan_limit_reached: stop the workflow when$statusCode == 403.
Keeps for the next steps:
product_id:$response.body#/idreview_status:$response.body#/review/status
As a workflow file
The workflow returns:
product_id:$steps.create_product.outputs.product_idreview_status:$steps.create_product.outputs.review_status
Values starting with $ are filled in as you go: $inputs.x is something you provide, $steps.s.outputs.o is a value an earlier step returned, and $response.body#/path a field of this response.
This recipe is the workflow submit_product of arazzo.json, an Arazzo 1.0 document that tools and AI agents can follow step by step.