Every endpoint of the Partner API, generated from the same OpenAPI 3.1 document the engine serves at GET /v1/openapi.json and this site at /openapi.json. Load that URL into your client generator or API tool — it carries CORS headers — or read it here.
Conventions
- Base URL
https://engine.layercrew.com/v1; HTTPS only;Authorization: Bearer <key>on every route except the spec itself. - Envelope:
{"data": …}for one object,{"data": [...], "meta": {page, per_page, total, total_pages}}for lists,{"error": {code, message, details?}}for errors. - Money is a string with two decimals in EUR. Timestamps are RFC 3339 in UTC. Ids are UUIDs; an order's number (
PA-YYYY-NNNN) is accepted wherever its id is. - Lists take
pageandper_page(25 by default, 100 at most) and return newest first. Event feeds takeafter(aseq) andlimit(50 by default, 200 at most) and return oldest first. - Every response carries
X-Request-ID. Rate-limited responses carryRetry-After,X-RateLimit-LimitandX-RateLimit-Remaining. - Request bodies are JSON up to 256 KiB.
POST /v1/ordersrequires anIdempotency-Key; other creates accept one. - The API version is
2026-10-24; every event carries it asapi_version.
Account
Who you are, your plan and your usage.
/v1/pingCheck your key
Confirms the key works and tells you which partner, environment and plan it belongs to.
Responses
200The key is valid.401The key is missing, malformed, unknown, revoked or for the other environment (INVALID_API_KEY,API_KEY_REVOKED,SCOPE_MISMATCH).403The partner account is not active (PARTNER_INACTIVE) or the route is test-only (TEST_ONLY).429Too many requests (RATE_LIMITED) or a monthly cap reached (QUOTA_EXCEEDED). HonourRetry-After.
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
partnerrequired | object | |
environmentrequired | Environmentlive · test | |
key_idrequired | string | |
planrequired | object | |
rate_limitrequired | object | |
server_timerequired | string (date-time) |
{
"data": {
"partner": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "LC-PT-0007",
"name": "Claire Martin"
},
"environment": "live",
"key_id": "k7m2p9q4r1s8t3u6",
"plan": {
"key": "key",
"name": "Claire Martin"
},
"rate_limit": {
"per_second": 2,
"burst": 10
},
"server_time": "2026-10-24T09:30:00Z"
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/ping" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/accountYour plan, limits, usage and agreement status
Responses
200The account.401The key is missing, malformed, unknown, revoked or for the other environment (INVALID_API_KEY,API_KEY_REVOKED,SCOPE_MISMATCH).429Too many requests (RATE_LIMITED) or a monthly cap reached (QUOTA_EXCEEDED). HonourRetry-After.
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
partnerrequired | object | |
statusrequired | enumpending_verification · pending_agreement · active · suspended · closed | |
planrequired | object | |
limitsrequired | PlanLimits | The limits in force for you (plan plus any agreed overrides). |
usagerequired | object | |
agreementsrequired | array of object |
{
"data": {
"partner": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "number",
"name": "Claire Martin",
"country_code": "FR",
"locale": "en"
},
"status": "pending_verification",
"plan": {
"key": "key",
"name": "Claire Martin"
},
"limits": {
"discount_pct": 1.5,
"rate_per_second": 2,
"burst": 10,
"monthly_request_cap": 0,
"monthly_order_cap": 0,
"monthly_test_order_cap": 0,
"max_file_bytes": 67108864,
"max_files": 0,
"max_items_per_order": 0,
"max_test_items_per_order": 0,
"max_quantity_per_item": 0,
"allowed_materials": [
"allowed materials"
],
"allowed_nozzles": [
"allowed nozzles"
],
"ship_before_payment": false,
"webhook_endpoints_max": 0,
"webhook_max_attempts": 12,
"test_file_retention_days": 0,
"file_retention_days_after_last_order": 0,
"recipient_retention_days": 90,
"quote_daily_cap": 0
},
"usage": {
"month": "2026-10",
"requests": 318,
"orders_live": 4,
"orders_test": 11,
"quotes_today": 2
},
"agreements": [
{
"document": "integration_agreement",
"version": "2026-10-24",
"status": "none",
"accepted_at": "2026-10-24T09:30:00Z",
"countersigned_at": "2026-10-24T09:30:00Z"
}
]
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/account" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/openapi.jsonno key neededThis document
Responses
200The OpenAPI 3.1 description of this API.
{}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/openapi.json"Materials
What you can order parts in.
/v1/materialsMaterials, nozzles and colours you can order
The list changes as the catalogue changes. Order with a material from this list; a colour is optional and must come from the material's colours when given. in_stock is live and never a promise.
Responses
200Materials.401The key is missing, malformed, unknown, revoked or for the other environment (INVALID_API_KEY,API_KEY_REVOKED,SCOPE_MISMATCH).
Fields of the 200 response (each item of data)
| Field | Type | Description |
|---|---|---|
materialrequired | string | |
description | string | |
nozzlesrequired | array of string | |
coloursrequired | array of object |
{
"data": [
{
"material": "PLA",
"description": "Production events",
"nozzles": [
"0.4"
],
"colours": [
{
"id": "id",
"name": "Claire Martin",
"hex": "#111111",
"in_stock": true
}
]
}
]
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/materials" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"Files
Upload the 3D files your orders reference.
/v1/filesList your files
Parameters
| Name | In | Type | Description |
|---|---|---|---|
page | query | integer | |
per_page | query | integer | |
status | query | FileStatus |
Responses
200Files, newest first.401The key is missing, malformed, unknown, revoked or for the other environment (INVALID_API_KEY,API_KEY_REVOKED,SCOPE_MISMATCH).
Fields of the 200 response (each item of data)
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
filenamerequired | string | |
formatrequired | FileFormatstl · obj · 3mf | |
statusrequired | FileStatuspending · ready · rejected · purged | |
size_bytesrequired | integer | |
sha256 | string | |
rejection_code | enum | nullsize_mismatch · hash_mismatch · not_a_model · too_complex · too_large · upload_missing | |
facts | object | What we read from the file: triangles, bounding box in mm, object count, producer. |
created_atrequired | string (date-time) | |
ready_at | string (date-time) | null | |
purge_after | string (date-time) | null | When the file will be deleted unless an order uses it. |
{
"data": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"filename": "bracket-v3.stl",
"format": "stl",
"status": "pending",
"size_bytes": 1048576,
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"rejection_code": null,
"facts": {
"triangles": 48210,
"objects": 1,
"bbox_mm": [
60,
42.5,
18
],
"producer": "Bambu Studio 02.08.02.61",
"sanitised": false
},
"created_at": "2026-10-24T09:30:00Z",
"ready_at": "2026-10-24T09:30:00Z",
"purge_after": "2026-10-24T09:30:00Z"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 1,
"total_pages": 1
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/files?page=1&per_page=25" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/filesStart an upload
Declares a file and returns a one-time upload URL. PUT the raw bytes to upload.url within upload.expires_at, sending exactly the headers in upload.headers (both Content-Type and x-goog-content-length-range are mandatory — the signature covers them). Then call complete. Formats: STL, OBJ, 3MF. STEP files are priced by an engineer: send them through https://layercrew.com/contact-us. Size limit: your plan's max_file_bytes. Units: millimetres.
Request body
| Field | Type | Description |
|---|---|---|
filenamerequired | string | With its extension: .stl, .obj or .3mf. (up to 200 characters) |
size_bytesrequired | integer | (at least 1) |
sha256required | string | Lowercase hex SHA-256 of the exact bytes you will upload. |
content_type | string | (default "application/octet-stream") |
{
"filename": "bracket-v3.stl",
"size_bytes": 1048576,
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"content_type": "application/octet-stream"
}Responses
201Upload instructions.401The key is missing, malformed, unknown, revoked or for the other environment (INVALID_API_KEY,API_KEY_REVOKED,SCOPE_MISMATCH).422A field is wrong;error.detailsmaps field names to messages (VALIDATION_ERROR,IDEMPOTENCY_KEY_REQUIRED,MATERIAL_UNAVAILABLE,FILE_REJECTED,ENDPOINT_URL_INVALID).429Too many requests (RATE_LIMITED) or a monthly cap reached (QUOTA_EXCEEDED). HonourRetry-After.
Fields of the 201 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
filenamerequired | string | |
formatrequired | FileFormatstl · obj · 3mf | |
statusrequired | FileStatuspending · ready · rejected · purged | |
size_bytesrequired | integer | |
sha256 | string | |
rejection_code | enum | nullsize_mismatch · hash_mismatch · not_a_model · too_complex · too_large · upload_missing | |
facts | object | What we read from the file: triangles, bounding box in mm, object count, producer. |
created_atrequired | string (date-time) | |
ready_at | string (date-time) | null | |
purge_after | string (date-time) | null | When the file will be deleted unless an order uses it. |
uploadrequired | object |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"filename": "bracket-v3.stl",
"format": "stl",
"status": "pending",
"size_bytes": 1048576,
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"rejection_code": null,
"facts": {
"triangles": 48210,
"objects": 1,
"bbox_mm": [
60,
42.5,
18
],
"producer": "Bambu Studio 02.08.02.61",
"sanitised": false
},
"created_at": "2026-10-24T09:30:00Z",
"ready_at": "2026-10-24T09:30:00Z",
"purge_after": "2026-10-24T09:30:00Z",
"upload": {
"method": "PUT",
"url": "https://shop.example.com/webhooks/layercrew",
"headers": {
"Content-Type": "application/octet-stream",
"x-goog-content-length-range": "0,1048576"
},
"expires_at": "2026-10-24T09:30:00Z"
}
}
}201 example
Call it
curl -X POST "https://engine.layercrew.com/v1/files" \
-H "Authorization: Bearer $LAYERCREW_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "bracket-v3.stl",
"size_bytes": 1048576,
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"content_type": "application/octet-stream"
}'/v1/files/{file_id}Get a file
Parameters
| Name | In | Type | Description |
|---|---|---|---|
file_idrequired | path | string (uuid) |
Responses
200The file.404No such object in this environment (NOT_FOUND).
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
filenamerequired | string | |
formatrequired | FileFormatstl · obj · 3mf | |
statusrequired | FileStatuspending · ready · rejected · purged | |
size_bytesrequired | integer | |
sha256 | string | |
rejection_code | enum | nullsize_mismatch · hash_mismatch · not_a_model · too_complex · too_large · upload_missing | |
facts | object | What we read from the file: triangles, bounding box in mm, object count, producer. |
created_atrequired | string (date-time) | |
ready_at | string (date-time) | null | |
purge_after | string (date-time) | null | When the file will be deleted unless an order uses it. |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"filename": "bracket-v3.stl",
"format": "stl",
"status": "pending",
"size_bytes": 1048576,
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"rejection_code": null,
"facts": {
"triangles": 48210,
"objects": 1,
"bbox_mm": [
60,
42.5,
18
],
"producer": "Bambu Studio 02.08.02.61",
"sanitised": false
},
"created_at": "2026-10-24T09:30:00Z",
"ready_at": "2026-10-24T09:30:00Z",
"purge_after": "2026-10-24T09:30:00Z"
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/files/4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/files/{file_id}Delete a file
A file no order uses is deleted now. A file used only by finished orders is scheduled for deletion within the hour (202). A file an open order, a pending quote or a running price job still needs answers 409 FILE_IN_USE and names it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
file_idrequired | path | string (uuid) |
Responses
202Scheduled for deletion.204Deleted.404No such object in this environment (NOT_FOUND).409The request conflicts with the current state;error.codesays how (REFERENCE_TAKEN,FILE_IN_USE,FILE_NOT_READY,CANNOT_CANCEL,ENDPOINT_LIMIT,DELIVERY_IN_FLIGHT,IDEMPOTENCY_KEY_REUSED,IDEMPOTENCY_IN_PROGRESS,TERMS_REACCEPTANCE_REQUIRED).
Call it
curl -X DELETE "https://engine.layercrew.com/v1/files/4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/files/{file_id}/completeFinish an upload
Verifies the uploaded bytes against the declared size and SHA-256, reads the model, strips any embedded slicer scripts from a 3MF, and stores the canonical copy. Idempotent: calling it again on a ready file returns the file. A file that fails verification is rejected with a rejection_code; upload a corrected file.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
file_idrequired | path | string (uuid) |
Responses
200The file is ready.404No such object in this environment (NOT_FOUND).409Another completion of this file is running.422The file was rejected;error.details.rejection_codesays why.
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
filenamerequired | string | |
formatrequired | FileFormatstl · obj · 3mf | |
statusrequired | FileStatuspending · ready · rejected · purged | |
size_bytesrequired | integer | |
sha256 | string | |
rejection_code | enum | nullsize_mismatch · hash_mismatch · not_a_model · too_complex · too_large · upload_missing | |
facts | object | What we read from the file: triangles, bounding box in mm, object count, producer. |
created_atrequired | string (date-time) | |
ready_at | string (date-time) | null | |
purge_after | string (date-time) | null | When the file will be deleted unless an order uses it. |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"filename": "bracket-v3.stl",
"format": "stl",
"status": "pending",
"size_bytes": 1048576,
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"rejection_code": null,
"facts": {
"triangles": 48210,
"objects": 1,
"bbox_mm": [
60,
42.5,
18
],
"producer": "Bambu Studio 02.08.02.61",
"sanitised": false
},
"created_at": "2026-10-24T09:30:00Z",
"ready_at": "2026-10-24T09:30:00Z",
"purge_after": "2026-10-24T09:30:00Z"
}
}200 example
Call it
curl -X POST "https://engine.layercrew.com/v1/files/4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d/complete" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"Quotes
Price a file before you order it.
/v1/quotesList your quotes
Parameters
| Name | In | Type | Description |
|---|---|---|---|
page | query | integer | |
per_page | query | integer |
Responses
200Quotes, newest first.
Fields of the 200 response (each item of data)
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
file_idrequired | string (uuid) | |
materialrequired | string | |
nozzlerequired | string | |
quantityrequired | integer | |
statusrequired | enumpending · priced · failed | |
unit_price | Money | EUR with two decimals, as a string. |
list_unit_price | Money | EUR with two decimals, as a string. |
discount_pct | string | |
total | Money | EUR with two decimals, as a string. |
currency | enumEUR | |
tiers | array of object | Unit price at other quantities. |
estimate | PriceEstimate | What the slicer measured and the settings it used. |
failure_code | enum | nullmodel_too_large · not_a_model · material_unavailable · slicer_rejected · file_unavailable | |
failure_message | string | null | |
created_atrequired | string (date-time) | |
priced_at | string (date-time) | null |
{
"data": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"file_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"material": "PLA",
"nozzle": "0.4",
"quantity": 2,
"status": "pending",
"unit_price": "12.40",
"list_unit_price": "12.40",
"discount_pct": "0",
"total": "12.40",
"currency": "EUR",
"tiers": [
{
"min_quantity": 1,
"unit_price": "12.40"
}
],
"estimate": {
"weight_grams": 31.2,
"time_seconds": 5400,
"unit_yield": 1,
"printer_model": "Bambu Lab A2L",
"nozzle": "0.4",
"material": "PLA",
"infill_pct": 15,
"wall_loops": 3,
"support": "auto",
"warnings": [
"warnings"
],
"priced_at": "2026-10-24T09:30:00Z"
},
"failure_code": null,
"failure_message": null,
"created_at": "2026-10-24T09:30:00Z",
"priced_at": "2026-10-24T09:30:00Z"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 1,
"total_pages": 1
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/quotes?page=1&per_page=25" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/quotesPrice a file
Prices one ready file in one material at one quantity. Pricing takes seconds to a few minutes (the file is sliced for real); poll the quote or listen for quote.priced. The price is the one an order of the same file, material and quantity would carry today; it is frozen on an order only when the order is accepted.
Request body
| Field | Type | Description |
|---|---|---|
file_idrequired | string (uuid) | |
materialrequired | string | |
nozzle | string | (default "0.4") |
quantityrequired | integer | (at least 1) |
{
"file_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"material": "PLA",
"nozzle": "0.4",
"quantity": 2
}Responses
202Pricing started.409The request conflicts with the current state;error.codesays how (REFERENCE_TAKEN,FILE_IN_USE,FILE_NOT_READY,CANNOT_CANCEL,ENDPOINT_LIMIT,DELIVERY_IN_FLIGHT,IDEMPOTENCY_KEY_REUSED,IDEMPOTENCY_IN_PROGRESS,TERMS_REACCEPTANCE_REQUIRED).422A field is wrong;error.detailsmaps field names to messages (VALIDATION_ERROR,IDEMPOTENCY_KEY_REQUIRED,MATERIAL_UNAVAILABLE,FILE_REJECTED,ENDPOINT_URL_INVALID).429Too many requests (RATE_LIMITED) or a monthly cap reached (QUOTA_EXCEEDED). HonourRetry-After.
Fields of the 202 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
file_idrequired | string (uuid) | |
materialrequired | string | |
nozzlerequired | string | |
quantityrequired | integer | |
statusrequired | enumpending · priced · failed | |
unit_price | Money | EUR with two decimals, as a string. |
list_unit_price | Money | EUR with two decimals, as a string. |
discount_pct | string | |
total | Money | EUR with two decimals, as a string. |
currency | enumEUR | |
tiers | array of object | Unit price at other quantities. |
estimate | PriceEstimate | What the slicer measured and the settings it used. |
failure_code | enum | nullmodel_too_large · not_a_model · material_unavailable · slicer_rejected · file_unavailable | |
failure_message | string | null | |
created_atrequired | string (date-time) | |
priced_at | string (date-time) | null |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"file_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"material": "PLA",
"nozzle": "0.4",
"quantity": 2,
"status": "pending",
"unit_price": "12.40",
"list_unit_price": "12.40",
"discount_pct": "0",
"total": "12.40",
"currency": "EUR",
"tiers": [
{
"min_quantity": 1,
"unit_price": "12.40"
}
],
"estimate": {
"weight_grams": 31.2,
"time_seconds": 5400,
"unit_yield": 1,
"printer_model": "Bambu Lab A2L",
"nozzle": "0.4",
"material": "PLA",
"infill_pct": 15,
"wall_loops": 3,
"support": "auto",
"warnings": [
"warnings"
],
"priced_at": "2026-10-24T09:30:00Z"
},
"failure_code": null,
"failure_message": null,
"created_at": "2026-10-24T09:30:00Z",
"priced_at": "2026-10-24T09:30:00Z"
}
}202 example
Call it
curl -X POST "https://engine.layercrew.com/v1/quotes" \
-H "Authorization: Bearer $LAYERCREW_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"file_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"material": "PLA",
"nozzle": "0.4",
"quantity": 2
}'/v1/quotes/{quote_id}Get a quote
Parameters
| Name | In | Type | Description |
|---|---|---|---|
quote_idrequired | path | string (uuid) |
Responses
200The quote.404No such object in this environment (NOT_FOUND).
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
file_idrequired | string (uuid) | |
materialrequired | string | |
nozzlerequired | string | |
quantityrequired | integer | |
statusrequired | enumpending · priced · failed | |
unit_price | Money | EUR with two decimals, as a string. |
list_unit_price | Money | EUR with two decimals, as a string. |
discount_pct | string | |
total | Money | EUR with two decimals, as a string. |
currency | enumEUR | |
tiers | array of object | Unit price at other quantities. |
estimate | PriceEstimate | What the slicer measured and the settings it used. |
failure_code | enum | nullmodel_too_large · not_a_model · material_unavailable · slicer_rejected · file_unavailable | |
failure_message | string | null | |
created_atrequired | string (date-time) | |
priced_at | string (date-time) | null |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"file_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"material": "PLA",
"nozzle": "0.4",
"quantity": 2,
"status": "pending",
"unit_price": "12.40",
"list_unit_price": "12.40",
"discount_pct": "0",
"total": "12.40",
"currency": "EUR",
"tiers": [
{
"min_quantity": 1,
"unit_price": "12.40"
}
],
"estimate": {
"weight_grams": 31.2,
"time_seconds": 5400,
"unit_yield": 1,
"printer_model": "Bambu Lab A2L",
"nozzle": "0.4",
"material": "PLA",
"infill_pct": 15,
"wall_loops": 3,
"support": "auto",
"warnings": [
"warnings"
],
"priced_at": "2026-10-24T09:30:00Z"
},
"failure_code": null,
"failure_message": null,
"created_at": "2026-10-24T09:30:00Z",
"priced_at": "2026-10-24T09:30:00Z"
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/quotes/4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"Orders
Create and follow production orders.
/v1/ordersList your orders
Parameters
| Name | In | Type | Description |
|---|---|---|---|
page | query | integer | |
per_page | query | integer | |
status | query | OrderStatus | |
reference | query | string | Exact match on your reference. |
created_after | query | string (date-time) |
Responses
200Orders, newest first.401The key is missing, malformed, unknown, revoked or for the other environment (INVALID_API_KEY,API_KEY_REVOKED,SCOPE_MISMATCH).
Fields of the 200 response (each item of data)
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
numberrequired | string | |
referencerequired | string | |
environmentrequired | Environmentlive · test | |
statusrequired | OrderStatusreceived · pending_review · accepting · accepted · in_production · ready_to_ship · shipped · delivered · on_hold · cancelled · rejected | received: pricing in progress · pending_review: priced, a LayerCrew engineer is looking at it · accepted: in the production queue · in_production · ready_to_ship: passed quality check and packed · shipped: handed to the courier · delivered (final) · on_hold: we need something, see hold · cancelled · rejected, see rejection. |
pricing_statusrequired | enumpending · priced · failed | |
itemsrequired | array of OrderItem | |
pricingrequired | Pricing | |
payment | Payment | |
deliveryrequired | Delivery | |
white_labelrequired | WhiteLabel | White label is on by default: neutral packaging, no LayerCrew marks on parts, packaging or inserts, no invoice in the box. The courier label names LayerCrew as the shipping account (a courier requirement) and shows your sender name as the contact line; packaging and inserts carry your branding settings. |
metadatarequired | object | |
notes | string | |
shipmentsrequired | array of Shipment | |
invoicesrequired | array of Invoice | |
rejection | Rejection | null | |
hold | Hold | null | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) | |
accepted_at | string (date-time) | null | |
shipped_at | string (date-time) | null | |
delivered_at | string (date-time) | null | |
cancelled_at | string (date-time) | null | |
linksrequired | object |
{
"data": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "PA-2026-0007",
"reference": "SHOP-10231",
"environment": "live",
"status": "received",
"pricing_status": "pending",
"items": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"position": 1,
"file": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"filename": "bracket-v3.stl",
"format": "stl"
},
"quantity": 2,
"material": "PLA",
"colour": "black",
"nozzle": "0.4",
"notes": "Fit check before the batch, please.",
"pricing_status": "pending",
"list_unit_price": "12.40",
"discount_pct": "0",
"unit_price": "12.40",
"line_total": "12.40",
"estimate": {
"weight_grams": 31.2,
"time_seconds": 5400,
"unit_yield": 1,
"printer_model": "Bambu Lab A2L",
"nozzle": "0.4",
"material": "PLA",
"infill_pct": 15,
"wall_loops": 3,
"support": "auto",
"warnings": [],
"priced_at": "2026-10-24T09:30:00Z"
},
"failure_code": null,
"failure_message": null
}
],
"pricing": {
"currency": "EUR",
"subtotal": "12.40",
"discount_total": "12.40",
"shipping_total": "12.40",
"tax_total": "12.40",
"tax_treatment": "standard",
"grand_total": "12.40",
"final": true
},
"payment": {
"method": "bank_transfer",
"status": "unpaid",
"ship_before_payment": false,
"amount_due": "12.40",
"instructions": {
"beneficiary": "LAYER CREW SRL",
"iban": "RO49AAAA1B31007593840000",
"bank": "Example Bank",
"reference": "SHOP-10231"
},
"paid_at": "2026-10-24T09:30:00Z"
},
"delivery": {
"name": "Claire Martin",
"company": "Atelier Martin",
"phone": "+33 6 12 34 56 78",
"email": "claire@example.com",
"line1": "12 rue de la Paix",
"line2": "Bâtiment B",
"city": "Lyon",
"region": "Auvergne-Rhône-Alpes",
"postal_code": "69001",
"country_code": "FR"
},
"white_label": {
"enabled": true,
"sender_name": "Studio NS",
"card_text": "Thank you for your order — Studio NS",
"packaging_preset": "neutral",
"no_invoice_in_box": true,
"language": "fr"
},
"metadata": {
"shop_order_id": "10231"
},
"notes": "Fit check before the batch, please.",
"shipments": [
{
"carrier": "FAN Courier",
"tracking_number": "2057100012345",
"tracking_url": "https://www.fancourier.ro/awb-tracking/?awb=2057100012345",
"status": "shipped",
"last_tracking_status": "last tracking status",
"shipped_at": "2026-10-24T09:30:00Z",
"delivered_at": "2026-10-24T09:30:00Z"
}
],
"invoices": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "number",
"kind": "fiscal",
"issued_at": "2026-10-24T09:30:00Z"
}
],
"rejection": null,
"hold": null,
"created_at": "2026-10-24T09:30:00Z",
"updated_at": "2026-10-24T09:30:00Z",
"accepted_at": "2026-10-24T09:30:00Z",
"shipped_at": "2026-10-24T09:30:00Z",
"delivered_at": "2026-10-24T09:30:00Z",
"cancelled_at": "2026-10-24T09:30:00Z",
"links": {
"self": "self",
"events": "events"
}
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 1,
"total_pages": 1
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/orders?page=1&per_page=25" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/ordersCreate an order
Creates a production order from ready files. Requires an Idempotency-Key header (any string up to 255 characters, unique per attempt; a retry with the same key and the same body returns the first response with Idempotent-Replayed: true). Your reference must be unique among your orders in this environment; a duplicate answers 409 REFERENCE_TAKEN with the existing order id. The order is priced within minutes (order.priced), then a LayerCrew engineer accepts it (order.accepted, usually within one business day) or declines it with a reason you can act on (order.rejected). Payment instructions appear on acceptance. Production starts after payment unless your plan says otherwise.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Keyrequired | header | string | Unique per attempt, up to 255 characters of [A-Za-z0-9._:~-]. Kept 24 hours. |
Request body
| Field | Type | Description |
|---|---|---|
referencerequired | string | Your own order reference; unique per environment. (up to 120 characters) |
itemsrequired | array of OrderItemCreate | |
deliveryrequired | Delivery | |
white_label | WhiteLabel | White label is on by default: neutral packaging, no LayerCrew marks on parts, packaging or inserts, no invoice in the box. The courier label names LayerCrew as the shipping account (a courier requirement) and shows your sender name as the contact line; packaging and inserts carry your branding settings. |
notes | string | (up to 2000 characters) |
metadata | object | Returned untouched on the order and in every webhook. (up to 20 keys) |
{
"reference": "SHOP-10231",
"items": [
{
"file_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"quantity": 2,
"material": "PLA",
"colour": "black",
"nozzle": "0.4",
"notes": "Fit check before the batch, please."
}
],
"delivery": {
"name": "Claire Martin",
"company": "Atelier Martin",
"phone": "+33 6 12 34 56 78",
"email": "claire@example.com",
"line1": "12 rue de la Paix",
"line2": "Bâtiment B",
"city": "Lyon",
"region": "Auvergne-Rhône-Alpes",
"postal_code": "69001",
"country_code": "FR"
},
"white_label": {
"enabled": true,
"sender_name": "Studio NS",
"card_text": "Thank you for your order — Studio NS",
"packaging_preset": "neutral",
"no_invoice_in_box": true,
"language": "fr"
},
"notes": "Fit check before the batch, please.",
"metadata": {
"shop_order_id": "10231"
}
}Responses
200Replayed from a previous request with the sameIdempotency-Key.202Order received; pricing started.401The key is missing, malformed, unknown, revoked or for the other environment (INVALID_API_KEY,API_KEY_REVOKED,SCOPE_MISMATCH).409The request conflicts with the current state;error.codesays how (REFERENCE_TAKEN,FILE_IN_USE,FILE_NOT_READY,CANNOT_CANCEL,ENDPOINT_LIMIT,DELIVERY_IN_FLIGHT,IDEMPOTENCY_KEY_REUSED,IDEMPOTENCY_IN_PROGRESS,TERMS_REACCEPTANCE_REQUIRED).422A field is wrong;error.detailsmaps field names to messages (VALIDATION_ERROR,IDEMPOTENCY_KEY_REQUIRED,MATERIAL_UNAVAILABLE,FILE_REJECTED,ENDPOINT_URL_INVALID).429Too many requests (RATE_LIMITED) or a monthly cap reached (QUOTA_EXCEEDED). HonourRetry-After.
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
numberrequired | string | |
referencerequired | string | |
environmentrequired | Environmentlive · test | |
statusrequired | OrderStatusreceived · pending_review · accepting · accepted · in_production · ready_to_ship · shipped · delivered · on_hold · cancelled · rejected | received: pricing in progress · pending_review: priced, a LayerCrew engineer is looking at it · accepted: in the production queue · in_production · ready_to_ship: passed quality check and packed · shipped: handed to the courier · delivered (final) · on_hold: we need something, see hold · cancelled · rejected, see rejection. |
pricing_statusrequired | enumpending · priced · failed | |
itemsrequired | array of OrderItem | |
pricingrequired | Pricing | |
payment | Payment | |
deliveryrequired | Delivery | |
white_labelrequired | WhiteLabel | White label is on by default: neutral packaging, no LayerCrew marks on parts, packaging or inserts, no invoice in the box. The courier label names LayerCrew as the shipping account (a courier requirement) and shows your sender name as the contact line; packaging and inserts carry your branding settings. |
metadatarequired | object | |
notes | string | |
shipmentsrequired | array of Shipment | |
invoicesrequired | array of Invoice | |
rejection | Rejection | null | |
hold | Hold | null | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) | |
accepted_at | string (date-time) | null | |
shipped_at | string (date-time) | null | |
delivered_at | string (date-time) | null | |
cancelled_at | string (date-time) | null | |
linksrequired | object |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "PA-2026-0007",
"reference": "SHOP-10231",
"environment": "live",
"status": "received",
"pricing_status": "pending",
"items": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"position": 1,
"file": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"filename": "bracket-v3.stl",
"format": "stl"
},
"quantity": 2,
"material": "PLA",
"colour": "black",
"nozzle": "0.4",
"notes": "Fit check before the batch, please.",
"pricing_status": "pending",
"list_unit_price": "12.40",
"discount_pct": "0",
"unit_price": "12.40",
"line_total": "12.40",
"estimate": {
"weight_grams": 31.2,
"time_seconds": 5400,
"unit_yield": 1,
"printer_model": "Bambu Lab A2L",
"nozzle": "0.4",
"material": "PLA",
"infill_pct": 15,
"wall_loops": 3,
"support": "auto",
"warnings": [
"warnings"
],
"priced_at": "2026-10-24T09:30:00Z"
},
"failure_code": null,
"failure_message": null
}
],
"pricing": {
"currency": "EUR",
"subtotal": "12.40",
"discount_total": "12.40",
"shipping_total": "12.40",
"tax_total": "12.40",
"tax_treatment": "standard",
"grand_total": "12.40",
"final": true
},
"payment": {
"method": "bank_transfer",
"status": "unpaid",
"ship_before_payment": false,
"amount_due": "12.40",
"instructions": {
"beneficiary": "LAYER CREW SRL",
"iban": "RO49AAAA1B31007593840000",
"bank": "Example Bank",
"reference": "SHOP-10231"
},
"paid_at": "2026-10-24T09:30:00Z"
},
"delivery": {
"name": "Claire Martin",
"company": "Atelier Martin",
"phone": "+33 6 12 34 56 78",
"email": "claire@example.com",
"line1": "12 rue de la Paix",
"line2": "Bâtiment B",
"city": "Lyon",
"region": "Auvergne-Rhône-Alpes",
"postal_code": "69001",
"country_code": "FR"
},
"white_label": {
"enabled": true,
"sender_name": "Studio NS",
"card_text": "Thank you for your order — Studio NS",
"packaging_preset": "neutral",
"no_invoice_in_box": true,
"language": "fr"
},
"metadata": {
"shop_order_id": "10231"
},
"notes": "Fit check before the batch, please.",
"shipments": [
{
"carrier": "FAN Courier",
"tracking_number": "2057100012345",
"tracking_url": "https://www.fancourier.ro/awb-tracking/?awb=2057100012345",
"status": "shipped",
"last_tracking_status": "last tracking status",
"shipped_at": "2026-10-24T09:30:00Z",
"delivered_at": "2026-10-24T09:30:00Z"
}
],
"invoices": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "number",
"kind": "fiscal",
"issued_at": "2026-10-24T09:30:00Z"
}
],
"rejection": null,
"hold": null,
"created_at": "2026-10-24T09:30:00Z",
"updated_at": "2026-10-24T09:30:00Z",
"accepted_at": "2026-10-24T09:30:00Z",
"shipped_at": "2026-10-24T09:30:00Z",
"delivered_at": "2026-10-24T09:30:00Z",
"cancelled_at": "2026-10-24T09:30:00Z",
"links": {
"self": "self",
"events": "events"
}
}
}200 example
Call it
curl -X POST "https://engine.layercrew.com/v1/orders" \
-H "Authorization: Bearer $LAYERCREW_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"reference": "SHOP-10231",
"items": [
{
"file_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"quantity": 2,
"material": "PLA",
"colour": "black",
"nozzle": "0.4",
"notes": "Fit check before the batch, please."
}
],
"delivery": {
"name": "Claire Martin",
"company": "Atelier Martin",
"phone": "+33 6 12 34 56 78",
"email": "claire@example.com",
"line1": "12 rue de la Paix",
"line2": "Bâtiment B",
"city": "Lyon",
"region": "Auvergne-Rhône-Alpes",
"postal_code": "69001",
"country_code": "FR"
},
"white_label": {
"enabled": true,
"sender_name": "Studio NS",
"card_text": "Thank you for your order — Studio NS",
"packaging_preset": "neutral",
"no_invoice_in_box": true,
"language": "fr"
},
"notes": "Fit check before the batch, please.",
"metadata": {
"shop_order_id": "10231"
}
}'/v1/orders/{order_id}Get an order
order_id is the order's id or its number (PA-2026-0007).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
order_idrequired | path | string | The order id (UUID) or number (PA-YYYY-NNNN). |
Responses
200The order.404No such object in this environment (NOT_FOUND).
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
numberrequired | string | |
referencerequired | string | |
environmentrequired | Environmentlive · test | |
statusrequired | OrderStatusreceived · pending_review · accepting · accepted · in_production · ready_to_ship · shipped · delivered · on_hold · cancelled · rejected | received: pricing in progress · pending_review: priced, a LayerCrew engineer is looking at it · accepted: in the production queue · in_production · ready_to_ship: passed quality check and packed · shipped: handed to the courier · delivered (final) · on_hold: we need something, see hold · cancelled · rejected, see rejection. |
pricing_statusrequired | enumpending · priced · failed | |
itemsrequired | array of OrderItem | |
pricingrequired | Pricing | |
payment | Payment | |
deliveryrequired | Delivery | |
white_labelrequired | WhiteLabel | White label is on by default: neutral packaging, no LayerCrew marks on parts, packaging or inserts, no invoice in the box. The courier label names LayerCrew as the shipping account (a courier requirement) and shows your sender name as the contact line; packaging and inserts carry your branding settings. |
metadatarequired | object | |
notes | string | |
shipmentsrequired | array of Shipment | |
invoicesrequired | array of Invoice | |
rejection | Rejection | null | |
hold | Hold | null | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) | |
accepted_at | string (date-time) | null | |
shipped_at | string (date-time) | null | |
delivered_at | string (date-time) | null | |
cancelled_at | string (date-time) | null | |
linksrequired | object |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "PA-2026-0007",
"reference": "SHOP-10231",
"environment": "live",
"status": "received",
"pricing_status": "pending",
"items": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"position": 1,
"file": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"filename": "bracket-v3.stl",
"format": "stl"
},
"quantity": 2,
"material": "PLA",
"colour": "black",
"nozzle": "0.4",
"notes": "Fit check before the batch, please.",
"pricing_status": "pending",
"list_unit_price": "12.40",
"discount_pct": "0",
"unit_price": "12.40",
"line_total": "12.40",
"estimate": {
"weight_grams": 31.2,
"time_seconds": 5400,
"unit_yield": 1,
"printer_model": "Bambu Lab A2L",
"nozzle": "0.4",
"material": "PLA",
"infill_pct": 15,
"wall_loops": 3,
"support": "auto",
"warnings": [
"warnings"
],
"priced_at": "2026-10-24T09:30:00Z"
},
"failure_code": null,
"failure_message": null
}
],
"pricing": {
"currency": "EUR",
"subtotal": "12.40",
"discount_total": "12.40",
"shipping_total": "12.40",
"tax_total": "12.40",
"tax_treatment": "standard",
"grand_total": "12.40",
"final": true
},
"payment": {
"method": "bank_transfer",
"status": "unpaid",
"ship_before_payment": false,
"amount_due": "12.40",
"instructions": {
"beneficiary": "LAYER CREW SRL",
"iban": "RO49AAAA1B31007593840000",
"bank": "Example Bank",
"reference": "SHOP-10231"
},
"paid_at": "2026-10-24T09:30:00Z"
},
"delivery": {
"name": "Claire Martin",
"company": "Atelier Martin",
"phone": "+33 6 12 34 56 78",
"email": "claire@example.com",
"line1": "12 rue de la Paix",
"line2": "Bâtiment B",
"city": "Lyon",
"region": "Auvergne-Rhône-Alpes",
"postal_code": "69001",
"country_code": "FR"
},
"white_label": {
"enabled": true,
"sender_name": "Studio NS",
"card_text": "Thank you for your order — Studio NS",
"packaging_preset": "neutral",
"no_invoice_in_box": true,
"language": "fr"
},
"metadata": {
"shop_order_id": "10231"
},
"notes": "Fit check before the batch, please.",
"shipments": [
{
"carrier": "FAN Courier",
"tracking_number": "2057100012345",
"tracking_url": "https://www.fancourier.ro/awb-tracking/?awb=2057100012345",
"status": "shipped",
"last_tracking_status": "last tracking status",
"shipped_at": "2026-10-24T09:30:00Z",
"delivered_at": "2026-10-24T09:30:00Z"
}
],
"invoices": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "number",
"kind": "fiscal",
"issued_at": "2026-10-24T09:30:00Z"
}
],
"rejection": null,
"hold": null,
"created_at": "2026-10-24T09:30:00Z",
"updated_at": "2026-10-24T09:30:00Z",
"accepted_at": "2026-10-24T09:30:00Z",
"shipped_at": "2026-10-24T09:30:00Z",
"delivered_at": "2026-10-24T09:30:00Z",
"cancelled_at": "2026-10-24T09:30:00Z",
"links": {
"self": "self",
"events": "events"
}
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/orders/PA-2026-0007" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/orders/{order_id}/eventsThe order's events, in order
Parameters
| Name | In | Type | Description |
|---|---|---|---|
order_idrequired | path | string | The order id (UUID) or number (PA-YYYY-NNNN). |
after | query | integer | Return events with seq greater than this. |
limit | query | integer |
Responses
200Events, oldest first.404No such object in this environment (NOT_FOUND).
Fields of the 200 response (each item of data)
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
typerequired | EventTypeorder.received · order.priced · order.pricing_failed · order.accepted · order.rejected · order.on_hold · order.released · order.in_production · order.ready_to_ship · order.shipped · order.tracking_updated · order.delivered · order.cancelled · order.paid · order.invoiced · order.returned · order.recipient_redacted · quote.priced · quote.failed · file.ready · file.rejected · file.purged · agreement.accepted · agreement.countersigned · key.issued · key.revoked · webhook_endpoint.disabled · webhook_endpoint.secret_rotated · partner.suspended · partner.activated · usage.warning · test.ping | |
api_versionrequired | string | |
created_atrequired | string (date-time) | |
seqrequired | integer | Per-partner, gap-free, strictly increasing. |
environmentrequired | Environmentlive · test | |
reason_code | string | null | |
datarequired | object | order for order.* events, quote for quote.*, file for file.*, endpoint for webhook_endpoint.*, key for key.* (never the secret), usage for usage.warning, {} for test.ping. |
{
"data": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"type": "order.received",
"api_version": "2026-10-24",
"created_at": "2026-10-24T09:30:00Z",
"seq": 1234,
"environment": "live",
"reason_code": null,
"data": {
"order": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "PA-2026-0007",
"reference": "SHOP-10231",
"environment": "live",
"status": "received",
"pricing_status": "pending",
"items": [
{
"id": null,
"position": null,
"file": null,
"quantity": null,
"material": null,
"colour": null,
"nozzle": null,
"notes": null,
"pricing_status": null,
"list_unit_price": null,
"discount_pct": null,
"unit_price": null,
"line_total": null,
"estimate": null,
"failure_code": null,
"failure_message": null
}
],
"pricing": {
"currency": "EUR",
"subtotal": "12.40",
"discount_total": "12.40",
"shipping_total": "12.40",
"tax_total": "12.40",
"tax_treatment": "standard",
"grand_total": "12.40",
"final": true
},
"payment": {
"method": "bank_transfer",
"status": "unpaid",
"ship_before_payment": false,
"amount_due": "12.40",
"instructions": {
"beneficiary": null,
"iban": null,
"bank": null,
"reference": null
},
"paid_at": "2026-10-24T09:30:00Z"
},
"delivery": {
"name": "Claire Martin",
"company": "Atelier Martin",
"phone": "+33 6 12 34 56 78",
"email": "claire@example.com",
"line1": "12 rue de la Paix",
"line2": "Bâtiment B",
"city": "Lyon",
"region": "Auvergne-Rhône-Alpes",
"postal_code": "69001",
"country_code": "FR"
},
"white_label": {
"enabled": true,
"sender_name": "Studio NS",
"card_text": "Thank you for your order — Studio NS",
"packaging_preset": "neutral",
"no_invoice_in_box": true,
"language": "fr"
},
"metadata": {
"shop_order_id": "10231"
},
"notes": "Fit check before the batch, please.",
"shipments": [
{
"carrier": null,
"tracking_number": null,
"tracking_url": null,
"status": null,
"last_tracking_status": null,
"shipped_at": null,
"delivered_at": null
}
],
"invoices": [
{
"id": null,
"number": null,
"kind": null,
"issued_at": null
}
],
"rejection": null,
"hold": null,
"created_at": "2026-10-24T09:30:00Z",
"updated_at": "2026-10-24T09:30:00Z",
"accepted_at": "2026-10-24T09:30:00Z",
"shipped_at": "2026-10-24T09:30:00Z",
"delivered_at": "2026-10-24T09:30:00Z",
"cancelled_at": "2026-10-24T09:30:00Z",
"links": {
"self": "self",
"events": "events"
}
},
"quote": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"file_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"material": "PLA",
"nozzle": "0.4",
"quantity": 2,
"status": "pending",
"unit_price": "12.40",
"list_unit_price": "12.40",
"discount_pct": "0",
"total": "12.40",
"currency": "EUR",
"tiers": [
{
"min_quantity": null,
"unit_price": null
}
],
"estimate": {
"weight_grams": 31.2,
"time_seconds": 5400,
"unit_yield": 1,
"printer_model": "Bambu Lab A2L",
"nozzle": "0.4",
"material": "PLA",
"infill_pct": 15,
"wall_loops": 3,
"support": "auto",
"warnings": [],
"priced_at": "2026-10-24T09:30:00Z"
},
"failure_code": null,
"failure_message": null,
"created_at": "2026-10-24T09:30:00Z",
"priced_at": "2026-10-24T09:30:00Z"
},
"file": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"filename": "bracket-v3.stl",
"format": "stl",
"status": "pending",
"size_bytes": 1048576,
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"rejection_code": null,
"facts": {
"triangles": 48210,
"objects": 1,
"bbox_mm": [
60,
42.5,
18
],
"producer": "Bambu Studio 02.08.02.61",
"sanitised": false
},
"created_at": "2026-10-24T09:30:00Z",
"ready_at": "2026-10-24T09:30:00Z",
"purge_after": "2026-10-24T09:30:00Z"
}
}
}
],
"meta": {
"next_after": 1234,
"has_more": false
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/orders/PA-2026-0007/events?after=0&limit=50" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/orders/{order_id}/cancelCancel an order
Allowed while the order is received, pending_review or accepted (before production starts). Later, write to us from the order page and we will tell you what is still possible.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
order_idrequired | path | string | The order id (UUID) or number (PA-YYYY-NNNN). |
Request body (optional)
| Field | Type | Description |
|---|---|---|
reason | string | (up to 500 characters) |
{
"reason": "Cancelled by the customer before production."
}Responses
200Cancelled.404No such object in this environment (NOT_FOUND).409The request conflicts with the current state;error.codesays how (REFERENCE_TAKEN,FILE_IN_USE,FILE_NOT_READY,CANNOT_CANCEL,ENDPOINT_LIMIT,DELIVERY_IN_FLIGHT,IDEMPOTENCY_KEY_REUSED,IDEMPOTENCY_IN_PROGRESS,TERMS_REACCEPTANCE_REQUIRED).
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
numberrequired | string | |
referencerequired | string | |
environmentrequired | Environmentlive · test | |
statusrequired | OrderStatusreceived · pending_review · accepting · accepted · in_production · ready_to_ship · shipped · delivered · on_hold · cancelled · rejected | received: pricing in progress · pending_review: priced, a LayerCrew engineer is looking at it · accepted: in the production queue · in_production · ready_to_ship: passed quality check and packed · shipped: handed to the courier · delivered (final) · on_hold: we need something, see hold · cancelled · rejected, see rejection. |
pricing_statusrequired | enumpending · priced · failed | |
itemsrequired | array of OrderItem | |
pricingrequired | Pricing | |
payment | Payment | |
deliveryrequired | Delivery | |
white_labelrequired | WhiteLabel | White label is on by default: neutral packaging, no LayerCrew marks on parts, packaging or inserts, no invoice in the box. The courier label names LayerCrew as the shipping account (a courier requirement) and shows your sender name as the contact line; packaging and inserts carry your branding settings. |
metadatarequired | object | |
notes | string | |
shipmentsrequired | array of Shipment | |
invoicesrequired | array of Invoice | |
rejection | Rejection | null | |
hold | Hold | null | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) | |
accepted_at | string (date-time) | null | |
shipped_at | string (date-time) | null | |
delivered_at | string (date-time) | null | |
cancelled_at | string (date-time) | null | |
linksrequired | object |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "PA-2026-0007",
"reference": "SHOP-10231",
"environment": "live",
"status": "received",
"pricing_status": "pending",
"items": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"position": 1,
"file": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"filename": "bracket-v3.stl",
"format": "stl"
},
"quantity": 2,
"material": "PLA",
"colour": "black",
"nozzle": "0.4",
"notes": "Fit check before the batch, please.",
"pricing_status": "pending",
"list_unit_price": "12.40",
"discount_pct": "0",
"unit_price": "12.40",
"line_total": "12.40",
"estimate": {
"weight_grams": 31.2,
"time_seconds": 5400,
"unit_yield": 1,
"printer_model": "Bambu Lab A2L",
"nozzle": "0.4",
"material": "PLA",
"infill_pct": 15,
"wall_loops": 3,
"support": "auto",
"warnings": [
"warnings"
],
"priced_at": "2026-10-24T09:30:00Z"
},
"failure_code": null,
"failure_message": null
}
],
"pricing": {
"currency": "EUR",
"subtotal": "12.40",
"discount_total": "12.40",
"shipping_total": "12.40",
"tax_total": "12.40",
"tax_treatment": "standard",
"grand_total": "12.40",
"final": true
},
"payment": {
"method": "bank_transfer",
"status": "unpaid",
"ship_before_payment": false,
"amount_due": "12.40",
"instructions": {
"beneficiary": "LAYER CREW SRL",
"iban": "RO49AAAA1B31007593840000",
"bank": "Example Bank",
"reference": "SHOP-10231"
},
"paid_at": "2026-10-24T09:30:00Z"
},
"delivery": {
"name": "Claire Martin",
"company": "Atelier Martin",
"phone": "+33 6 12 34 56 78",
"email": "claire@example.com",
"line1": "12 rue de la Paix",
"line2": "Bâtiment B",
"city": "Lyon",
"region": "Auvergne-Rhône-Alpes",
"postal_code": "69001",
"country_code": "FR"
},
"white_label": {
"enabled": true,
"sender_name": "Studio NS",
"card_text": "Thank you for your order — Studio NS",
"packaging_preset": "neutral",
"no_invoice_in_box": true,
"language": "fr"
},
"metadata": {
"shop_order_id": "10231"
},
"notes": "Fit check before the batch, please.",
"shipments": [
{
"carrier": "FAN Courier",
"tracking_number": "2057100012345",
"tracking_url": "https://www.fancourier.ro/awb-tracking/?awb=2057100012345",
"status": "shipped",
"last_tracking_status": "last tracking status",
"shipped_at": "2026-10-24T09:30:00Z",
"delivered_at": "2026-10-24T09:30:00Z"
}
],
"invoices": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "number",
"kind": "fiscal",
"issued_at": "2026-10-24T09:30:00Z"
}
],
"rejection": null,
"hold": null,
"created_at": "2026-10-24T09:30:00Z",
"updated_at": "2026-10-24T09:30:00Z",
"accepted_at": "2026-10-24T09:30:00Z",
"shipped_at": "2026-10-24T09:30:00Z",
"delivered_at": "2026-10-24T09:30:00Z",
"cancelled_at": "2026-10-24T09:30:00Z",
"links": {
"self": "self",
"events": "events"
}
}
}200 example
Call it
curl -X POST "https://engine.layercrew.com/v1/orders/PA-2026-0007/cancel" \
-H "Authorization: Bearer $LAYERCREW_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reason": "Cancelled by the customer before production."
}'/v1/orders/{order_id}/invoicesInvoices issued for the order
Parameters
| Name | In | Type | Description |
|---|---|---|---|
order_idrequired | path | string | The order id (UUID) or number (PA-YYYY-NNNN). |
Responses
200Invoices.404No such object in this environment (NOT_FOUND).
Fields of the 200 response (each item of data)
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
numberrequired | string | |
kindrequired | enumfiscal · proforma · storno | |
issued_atrequired | string (date-time) |
{
"data": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "number",
"kind": "fiscal",
"issued_at": "2026-10-24T09:30:00Z"
}
]
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/orders/PA-2026-0007/invoices" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/orders/{order_id}/invoices/{invoice_id}/download-urlA 15-minute link to the invoice PDF
Parameters
| Name | In | Type | Description |
|---|---|---|---|
order_idrequired | path | string | The order id (UUID) or number (PA-YYYY-NNNN). |
invoice_idrequired | path | string (uuid) |
Responses
200The link.404No such object in this environment (NOT_FOUND).
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
urlrequired | string (uri) | |
expires_atrequired | string (date-time) |
{
"data": {
"url": "https://shop.example.com/webhooks/layercrew",
"expires_at": "2026-10-24T09:30:00Z"
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/orders/PA-2026-0007/invoices/4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d/download-url" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/orders/{order_id}/recipientErase your customer's personal data from a finished order
Replaces the recipient's name, company, phone, email and street lines with [redacted] on the order and on its stored events; city, postal code and country stay for fiscal and zone records. Allowed once the order is delivered, cancelled or rejected. We also do this automatically after the retention window in your plan.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
order_idrequired | path | string | The order id (UUID) or number (PA-YYYY-NNNN). |
Responses
204Erased.404No such object in this environment (NOT_FOUND).409The request conflicts with the current state;error.codesays how (REFERENCE_TAKEN,FILE_IN_USE,FILE_NOT_READY,CANNOT_CANCEL,ENDPOINT_LIMIT,DELIVERY_IN_FLIGHT,IDEMPOTENCY_KEY_REUSED,IDEMPOTENCY_IN_PROGRESS,TERMS_REACCEPTANCE_REQUIRED).
Call it
curl -X DELETE "https://engine.layercrew.com/v1/orders/PA-2026-0007/recipient" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"Events
The ordered feed of everything that happened to your account.
/v1/eventsEverything that happened, in order
The authoritative, gap-free sequence of your account's events in this environment. Poll with after = the last seq you processed. Webhooks carry the same events; this feed is the source of truth when a webhook is late or missed.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
after | query | integer | Return events with seq greater than this. |
limit | query | integer | |
types | query | string | Comma-separated event types to include. |
Responses
200Events, oldest first.401The key is missing, malformed, unknown, revoked or for the other environment (INVALID_API_KEY,API_KEY_REVOKED,SCOPE_MISMATCH).
Fields of the 200 response (each item of data)
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
typerequired | EventTypeorder.received · order.priced · order.pricing_failed · order.accepted · order.rejected · order.on_hold · order.released · order.in_production · order.ready_to_ship · order.shipped · order.tracking_updated · order.delivered · order.cancelled · order.paid · order.invoiced · order.returned · order.recipient_redacted · quote.priced · quote.failed · file.ready · file.rejected · file.purged · agreement.accepted · agreement.countersigned · key.issued · key.revoked · webhook_endpoint.disabled · webhook_endpoint.secret_rotated · partner.suspended · partner.activated · usage.warning · test.ping | |
api_versionrequired | string | |
created_atrequired | string (date-time) | |
seqrequired | integer | Per-partner, gap-free, strictly increasing. |
environmentrequired | Environmentlive · test | |
reason_code | string | null | |
datarequired | object | order for order.* events, quote for quote.*, file for file.*, endpoint for webhook_endpoint.*, key for key.* (never the secret), usage for usage.warning, {} for test.ping. |
{
"data": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"type": "order.received",
"api_version": "2026-10-24",
"created_at": "2026-10-24T09:30:00Z",
"seq": 1234,
"environment": "live",
"reason_code": null,
"data": {
"order": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "PA-2026-0007",
"reference": "SHOP-10231",
"environment": "live",
"status": "received",
"pricing_status": "pending",
"items": [
{
"id": null,
"position": null,
"file": null,
"quantity": null,
"material": null,
"colour": null,
"nozzle": null,
"notes": null,
"pricing_status": null,
"list_unit_price": null,
"discount_pct": null,
"unit_price": null,
"line_total": null,
"estimate": null,
"failure_code": null,
"failure_message": null
}
],
"pricing": {
"currency": "EUR",
"subtotal": "12.40",
"discount_total": "12.40",
"shipping_total": "12.40",
"tax_total": "12.40",
"tax_treatment": "standard",
"grand_total": "12.40",
"final": true
},
"payment": {
"method": "bank_transfer",
"status": "unpaid",
"ship_before_payment": false,
"amount_due": "12.40",
"instructions": {
"beneficiary": null,
"iban": null,
"bank": null,
"reference": null
},
"paid_at": "2026-10-24T09:30:00Z"
},
"delivery": {
"name": "Claire Martin",
"company": "Atelier Martin",
"phone": "+33 6 12 34 56 78",
"email": "claire@example.com",
"line1": "12 rue de la Paix",
"line2": "Bâtiment B",
"city": "Lyon",
"region": "Auvergne-Rhône-Alpes",
"postal_code": "69001",
"country_code": "FR"
},
"white_label": {
"enabled": true,
"sender_name": "Studio NS",
"card_text": "Thank you for your order — Studio NS",
"packaging_preset": "neutral",
"no_invoice_in_box": true,
"language": "fr"
},
"metadata": {
"shop_order_id": "10231"
},
"notes": "Fit check before the batch, please.",
"shipments": [
{
"carrier": null,
"tracking_number": null,
"tracking_url": null,
"status": null,
"last_tracking_status": null,
"shipped_at": null,
"delivered_at": null
}
],
"invoices": [
{
"id": null,
"number": null,
"kind": null,
"issued_at": null
}
],
"rejection": null,
"hold": null,
"created_at": "2026-10-24T09:30:00Z",
"updated_at": "2026-10-24T09:30:00Z",
"accepted_at": "2026-10-24T09:30:00Z",
"shipped_at": "2026-10-24T09:30:00Z",
"delivered_at": "2026-10-24T09:30:00Z",
"cancelled_at": "2026-10-24T09:30:00Z",
"links": {
"self": "self",
"events": "events"
}
},
"quote": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"file_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"material": "PLA",
"nozzle": "0.4",
"quantity": 2,
"status": "pending",
"unit_price": "12.40",
"list_unit_price": "12.40",
"discount_pct": "0",
"total": "12.40",
"currency": "EUR",
"tiers": [
{
"min_quantity": null,
"unit_price": null
}
],
"estimate": {
"weight_grams": 31.2,
"time_seconds": 5400,
"unit_yield": 1,
"printer_model": "Bambu Lab A2L",
"nozzle": "0.4",
"material": "PLA",
"infill_pct": 15,
"wall_loops": 3,
"support": "auto",
"warnings": [],
"priced_at": "2026-10-24T09:30:00Z"
},
"failure_code": null,
"failure_message": null,
"created_at": "2026-10-24T09:30:00Z",
"priced_at": "2026-10-24T09:30:00Z"
},
"file": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"filename": "bracket-v3.stl",
"format": "stl",
"status": "pending",
"size_bytes": 1048576,
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"rejection_code": null,
"facts": {
"triangles": 48210,
"objects": 1,
"bbox_mm": [
60,
42.5,
18
],
"producer": "Bambu Studio 02.08.02.61",
"sanitised": false
},
"created_at": "2026-10-24T09:30:00Z",
"ready_at": "2026-10-24T09:30:00Z",
"purge_after": "2026-10-24T09:30:00Z"
}
}
}
],
"meta": {
"next_after": 1234,
"has_more": false
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/events?after=0&limit=50" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"Webhooks
Signed HTTP notifications and their delivery log.
/v1/webhook-endpointsList endpoints
Responses
200Endpoints.
Fields of the 200 response (each item of data)
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
urlrequired | string | |
description | string | |
environmentrequired | Environmentlive · test | |
event_typesrequired | array of string | null | |
enabledrequired | boolean | |
disabled_reason | string | null | |
consecutive_failures | integer | |
last_success_at | string (date-time) | null | |
secret_rotated_at | string (date-time) | null | |
created_atrequired | string (date-time) |
{
"data": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"url": "https://shop.example.com/webhooks/layercrew",
"description": "Production events",
"environment": "live",
"event_types": [
"event types"
],
"enabled": true,
"disabled_reason": null,
"consecutive_failures": 0,
"last_success_at": "2026-10-24T09:30:00Z",
"secret_rotated_at": "2026-10-24T09:30:00Z",
"created_at": "2026-10-24T09:30:00Z"
}
]
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/webhook-endpoints" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/webhook-endpointsRegister an endpoint
The URL must be HTTPS on port 443 (or 8443) on a public host. The signing secret is returned once; store it. Each delivery carries webhook-id, webhook-timestamp and webhook-signature (Standard Webhooks). Your plan caps the number of endpoints per environment.
Request body
| Field | Type | Description |
|---|---|---|
urlrequired | string (uri) | (up to 500 characters) |
description | string | (up to 200 characters) |
event_types | array of EventType | null | null = every event. |
{
"url": "https://shop.example.com/webhooks/layercrew",
"description": "Production events",
"event_types": [
"order.received"
]
}Responses
201Created;secretis shown once.409The request conflicts with the current state;error.codesays how (REFERENCE_TAKEN,FILE_IN_USE,FILE_NOT_READY,CANNOT_CANCEL,ENDPOINT_LIMIT,DELIVERY_IN_FLIGHT,IDEMPOTENCY_KEY_REUSED,IDEMPOTENCY_IN_PROGRESS,TERMS_REACCEPTANCE_REQUIRED).422A field is wrong;error.detailsmaps field names to messages (VALIDATION_ERROR,IDEMPOTENCY_KEY_REQUIRED,MATERIAL_UNAVAILABLE,FILE_REJECTED,ENDPOINT_URL_INVALID).
Fields of the 201 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
urlrequired | string | |
description | string | |
environmentrequired | Environmentlive · test | |
event_typesrequired | array of string | null | |
enabledrequired | boolean | |
disabled_reason | string | null | |
consecutive_failures | integer | |
last_success_at | string (date-time) | null | |
secret_rotated_at | string (date-time) | null | |
created_atrequired | string (date-time) | |
secretrequired | string | whsec_ + base64. Shown once. |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"url": "https://shop.example.com/webhooks/layercrew",
"description": "Production events",
"environment": "live",
"event_types": [
"event types"
],
"enabled": true,
"disabled_reason": null,
"consecutive_failures": 0,
"last_success_at": "2026-10-24T09:30:00Z",
"secret_rotated_at": "2026-10-24T09:30:00Z",
"created_at": "2026-10-24T09:30:00Z",
"secret": "secret"
}
}201 example
Call it
curl -X POST "https://engine.layercrew.com/v1/webhook-endpoints" \
-H "Authorization: Bearer $LAYERCREW_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://shop.example.com/webhooks/layercrew",
"description": "Production events",
"event_types": [
"order.received"
]
}'/v1/webhook-endpoints/{endpoint_id}Get an endpoint
Parameters
| Name | In | Type | Description |
|---|---|---|---|
endpoint_idrequired | path | string (uuid) |
Responses
200The endpoint.404No such object in this environment (NOT_FOUND).
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
urlrequired | string | |
description | string | |
environmentrequired | Environmentlive · test | |
event_typesrequired | array of string | null | |
enabledrequired | boolean | |
disabled_reason | string | null | |
consecutive_failures | integer | |
last_success_at | string (date-time) | null | |
secret_rotated_at | string (date-time) | null | |
created_atrequired | string (date-time) |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"url": "https://shop.example.com/webhooks/layercrew",
"description": "Production events",
"environment": "live",
"event_types": [
"event types"
],
"enabled": true,
"disabled_reason": null,
"consecutive_failures": 0,
"last_success_at": "2026-10-24T09:30:00Z",
"secret_rotated_at": "2026-10-24T09:30:00Z",
"created_at": "2026-10-24T09:30:00Z"
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/webhook-endpoints/4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/webhook-endpoints/{endpoint_id}Update an endpoint
Re-enabling a disabled endpoint resets its failure count and re-queues deliveries skipped in the last 7 days, in order.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
endpoint_idrequired | path | string (uuid) |
Request body
| Field | Type | Description |
|---|---|---|
url | string (uri) | |
description | string | |
event_types | array of EventType | null | |
enabled | boolean |
{
"url": "https://shop.example.com/webhooks/layercrew",
"description": "Production events",
"event_types": [
"order.received"
],
"enabled": true
}Responses
200Updated.404No such object in this environment (NOT_FOUND).422A field is wrong;error.detailsmaps field names to messages (VALIDATION_ERROR,IDEMPOTENCY_KEY_REQUIRED,MATERIAL_UNAVAILABLE,FILE_REJECTED,ENDPOINT_URL_INVALID).
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
urlrequired | string | |
description | string | |
environmentrequired | Environmentlive · test | |
event_typesrequired | array of string | null | |
enabledrequired | boolean | |
disabled_reason | string | null | |
consecutive_failures | integer | |
last_success_at | string (date-time) | null | |
secret_rotated_at | string (date-time) | null | |
created_atrequired | string (date-time) |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"url": "https://shop.example.com/webhooks/layercrew",
"description": "Production events",
"environment": "live",
"event_types": [
"event types"
],
"enabled": true,
"disabled_reason": null,
"consecutive_failures": 0,
"last_success_at": "2026-10-24T09:30:00Z",
"secret_rotated_at": "2026-10-24T09:30:00Z",
"created_at": "2026-10-24T09:30:00Z"
}
}200 example
Call it
curl -X PATCH "https://engine.layercrew.com/v1/webhook-endpoints/4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d" \
-H "Authorization: Bearer $LAYERCREW_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://shop.example.com/webhooks/layercrew",
"description": "Production events",
"event_types": [
"order.received"
],
"enabled": true
}'/v1/webhook-endpoints/{endpoint_id}Delete an endpoint
Parameters
| Name | In | Type | Description |
|---|---|---|---|
endpoint_idrequired | path | string (uuid) |
Responses
204Deleted.404No such object in this environment (NOT_FOUND).
Call it
curl -X DELETE "https://engine.layercrew.com/v1/webhook-endpoints/4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/webhook-endpoints/{endpoint_id}/rotate-secretRotate the signing secret
Returns a new secret once. For 24 hours every delivery is signed with both the new and the old secret, so you can switch without a gap.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
endpoint_idrequired | path | string (uuid) |
Responses
200Rotated.404No such object in this environment (NOT_FOUND).
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
urlrequired | string | |
description | string | |
environmentrequired | Environmentlive · test | |
event_typesrequired | array of string | null | |
enabledrequired | boolean | |
disabled_reason | string | null | |
consecutive_failures | integer | |
last_success_at | string (date-time) | null | |
secret_rotated_at | string (date-time) | null | |
created_atrequired | string (date-time) | |
secretrequired | string | whsec_ + base64. Shown once. |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"url": "https://shop.example.com/webhooks/layercrew",
"description": "Production events",
"environment": "live",
"event_types": [
"event types"
],
"enabled": true,
"disabled_reason": null,
"consecutive_failures": 0,
"last_success_at": "2026-10-24T09:30:00Z",
"secret_rotated_at": "2026-10-24T09:30:00Z",
"created_at": "2026-10-24T09:30:00Z",
"secret": "secret"
}
}200 example
Call it
curl -X POST "https://engine.layercrew.com/v1/webhook-endpoints/4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d/rotate-secret" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/webhook-endpoints/{endpoint_id}/pingSend a signed test event
Queues a test.ping delivery so you can verify your signature check before going live.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
endpoint_idrequired | path | string (uuid) |
Responses
202Queued.404No such object in this environment (NOT_FOUND).
Fields of the 202 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
endpoint_idrequired | string (uuid) | |
event_idrequired | string (uuid) | |
event_typerequired | string | |
seqrequired | integer | |
statusrequired | DeliveryStatuspending · in_flight · delivered · failed · skipped | |
attemptsrequired | integer | |
max_attempts | integer | |
next_attempt_at | string (date-time) | null | |
last_status_code | integer | null | |
last_error | string | null | |
delivered_at | string (date-time) | null | |
created_atrequired | string (date-time) |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"endpoint_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"event_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"event_type": "event type",
"seq": 1234,
"status": "pending",
"attempts": 1,
"max_attempts": 12,
"next_attempt_at": "2026-10-24T09:30:00Z",
"last_status_code": 200,
"last_error": null,
"delivered_at": "2026-10-24T09:30:00Z",
"created_at": "2026-10-24T09:30:00Z"
}
}202 example
Call it
curl -X POST "https://engine.layercrew.com/v1/webhook-endpoints/4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d/ping" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/webhook-deliveriesDelivery log
Parameters
| Name | In | Type | Description |
|---|---|---|---|
page | query | integer | |
per_page | query | integer | |
endpoint_id | query | string (uuid) | |
status | query | DeliveryStatus | |
event_id | query | string (uuid) |
Responses
200Deliveries, newest first.
Fields of the 200 response (each item of data)
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
endpoint_idrequired | string (uuid) | |
event_idrequired | string (uuid) | |
event_typerequired | string | |
seqrequired | integer | |
statusrequired | DeliveryStatuspending · in_flight · delivered · failed · skipped | |
attemptsrequired | integer | |
max_attempts | integer | |
next_attempt_at | string (date-time) | null | |
last_status_code | integer | null | |
last_error | string | null | |
delivered_at | string (date-time) | null | |
created_atrequired | string (date-time) |
{
"data": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"endpoint_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"event_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"event_type": "event type",
"seq": 1234,
"status": "pending",
"attempts": 1,
"max_attempts": 12,
"next_attempt_at": "2026-10-24T09:30:00Z",
"last_status_code": 200,
"last_error": null,
"delivered_at": "2026-10-24T09:30:00Z",
"created_at": "2026-10-24T09:30:00Z"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 1,
"total_pages": 1
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/webhook-deliveries?page=1&per_page=25" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/webhook-deliveries/{delivery_id}A delivery with every attempt
Parameters
| Name | In | Type | Description |
|---|---|---|---|
delivery_idrequired | path | string (uuid) |
Responses
200The delivery.404No such object in this environment (NOT_FOUND).
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
endpoint_idrequired | string (uuid) | |
event_idrequired | string (uuid) | |
event_typerequired | string | |
seqrequired | integer | |
statusrequired | DeliveryStatuspending · in_flight · delivered · failed · skipped | |
attemptsrequired | integer | |
max_attempts | integer | |
next_attempt_at | string (date-time) | null | |
last_status_code | integer | null | |
last_error | string | null | |
delivered_at | string (date-time) | null | |
created_atrequired | string (date-time) | |
attempts_logrequired | array of WebhookAttempt | |
eventrequired | Event |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"endpoint_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"event_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"event_type": "event type",
"seq": 1234,
"status": "pending",
"attempts": 1,
"max_attempts": 12,
"next_attempt_at": "2026-10-24T09:30:00Z",
"last_status_code": 200,
"last_error": null,
"delivered_at": "2026-10-24T09:30:00Z",
"created_at": "2026-10-24T09:30:00Z",
"attempts_log": [
{
"attempt": 1,
"at": "2026-10-24T09:30:00Z",
"request_id": "01J9Z8Y7X6W5V4U3T2S1R0Q9P8",
"status_code": 200,
"duration_ms": 42,
"error": "error",
"response_snippet": "ok"
}
],
"event": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"type": "order.received",
"api_version": "2026-10-24",
"created_at": "2026-10-24T09:30:00Z",
"seq": 1234,
"environment": "live",
"reason_code": null,
"data": {
"order": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "PA-2026-0007",
"reference": "SHOP-10231",
"environment": "live",
"status": "received",
"pricing_status": "pending",
"items": [
{
"id": null,
"position": null,
"file": null,
"quantity": null,
"material": null,
"colour": null,
"nozzle": null,
"notes": null,
"pricing_status": null,
"list_unit_price": null,
"discount_pct": null,
"unit_price": null,
"line_total": null,
"estimate": null,
"failure_code": null,
"failure_message": null
}
],
"pricing": {
"currency": "EUR",
"subtotal": "12.40",
"discount_total": "12.40",
"shipping_total": "12.40",
"tax_total": "12.40",
"tax_treatment": "standard",
"grand_total": "12.40",
"final": true
},
"payment": {
"method": "bank_transfer",
"status": "unpaid",
"ship_before_payment": false,
"amount_due": "12.40",
"instructions": {
"beneficiary": null,
"iban": null,
"bank": null,
"reference": null
},
"paid_at": "2026-10-24T09:30:00Z"
},
"delivery": {
"name": "Claire Martin",
"company": "Atelier Martin",
"phone": "+33 6 12 34 56 78",
"email": "claire@example.com",
"line1": "12 rue de la Paix",
"line2": "Bâtiment B",
"city": "Lyon",
"region": "Auvergne-Rhône-Alpes",
"postal_code": "69001",
"country_code": "FR"
},
"white_label": {
"enabled": true,
"sender_name": "Studio NS",
"card_text": "Thank you for your order — Studio NS",
"packaging_preset": "neutral",
"no_invoice_in_box": true,
"language": "fr"
},
"metadata": {
"shop_order_id": "10231"
},
"notes": "Fit check before the batch, please.",
"shipments": [
{
"carrier": null,
"tracking_number": null,
"tracking_url": null,
"status": null,
"last_tracking_status": null,
"shipped_at": null,
"delivered_at": null
}
],
"invoices": [
{
"id": null,
"number": null,
"kind": null,
"issued_at": null
}
],
"rejection": null,
"hold": null,
"created_at": "2026-10-24T09:30:00Z",
"updated_at": "2026-10-24T09:30:00Z",
"accepted_at": "2026-10-24T09:30:00Z",
"shipped_at": "2026-10-24T09:30:00Z",
"delivered_at": "2026-10-24T09:30:00Z",
"cancelled_at": "2026-10-24T09:30:00Z",
"links": {
"self": "self",
"events": "events"
}
},
"quote": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"file_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"material": "PLA",
"nozzle": "0.4",
"quantity": 2,
"status": "pending",
"unit_price": "12.40",
"list_unit_price": "12.40",
"discount_pct": "0",
"total": "12.40",
"currency": "EUR",
"tiers": [
{
"min_quantity": null,
"unit_price": null
}
],
"estimate": {
"weight_grams": 31.2,
"time_seconds": 5400,
"unit_yield": 1,
"printer_model": "Bambu Lab A2L",
"nozzle": "0.4",
"material": "PLA",
"infill_pct": 15,
"wall_loops": 3,
"support": "auto",
"warnings": [],
"priced_at": "2026-10-24T09:30:00Z"
},
"failure_code": null,
"failure_message": null,
"created_at": "2026-10-24T09:30:00Z",
"priced_at": "2026-10-24T09:30:00Z"
},
"file": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"filename": "bracket-v3.stl",
"format": "stl",
"status": "pending",
"size_bytes": 1048576,
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"rejection_code": null,
"facts": {
"triangles": 48210,
"objects": 1,
"bbox_mm": [
60,
42.5,
18
],
"producer": "Bambu Studio 02.08.02.61",
"sanitised": false
},
"created_at": "2026-10-24T09:30:00Z",
"ready_at": "2026-10-24T09:30:00Z",
"purge_after": "2026-10-24T09:30:00Z"
}
}
}
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/webhook-deliveries/4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/webhook-deliveries/{delivery_id}/redeliverSend a delivery again
Allowed for delivered, failed and skipped deliveries; a delivery in flight answers 409. The exact original bytes are re-sent with a fresh signature and timestamp.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
delivery_idrequired | path | string (uuid) |
Responses
202Queued.404No such object in this environment (NOT_FOUND).409The request conflicts with the current state;error.codesays how (REFERENCE_TAKEN,FILE_IN_USE,FILE_NOT_READY,CANNOT_CANCEL,ENDPOINT_LIMIT,DELIVERY_IN_FLIGHT,IDEMPOTENCY_KEY_REUSED,IDEMPOTENCY_IN_PROGRESS,TERMS_REACCEPTANCE_REQUIRED).
Fields of the 202 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
endpoint_idrequired | string (uuid) | |
event_idrequired | string (uuid) | |
event_typerequired | string | |
seqrequired | integer | |
statusrequired | DeliveryStatuspending · in_flight · delivered · failed · skipped | |
attemptsrequired | integer | |
max_attempts | integer | |
next_attempt_at | string (date-time) | null | |
last_status_code | integer | null | |
last_error | string | null | |
delivered_at | string (date-time) | null | |
created_atrequired | string (date-time) |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"endpoint_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"event_id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"event_type": "event type",
"seq": 1234,
"status": "pending",
"attempts": 1,
"max_attempts": 12,
"next_attempt_at": "2026-10-24T09:30:00Z",
"last_status_code": 200,
"last_error": null,
"delivered_at": "2026-10-24T09:30:00Z",
"created_at": "2026-10-24T09:30:00Z"
}
}202 example
Call it
curl -X POST "https://engine.layercrew.com/v1/webhook-deliveries/4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d/redeliver" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"Requests
Your own request log, for debugging.
/v1/requestsYour request log
Every call made with your keys in the last 90 days: when, which route, the status, the duration and the request id to quote to support. Bodies are never stored.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
page | query | integer | |
per_page | query | integer | |
from | query | string (date-time) | |
to | query | string (date-time) | |
status | query | integer | |
route | query | string |
Responses
200Requests, newest first.
Fields of the 200 response (each item of data)
| Field | Type | Description |
|---|---|---|
request_idrequired | string | |
client_request_id | string | null | |
key_id | string | |
methodrequired | string | |
routerequired | string | |
path | string | |
statusrequired | integer | |
error_code | string | null | |
duration_msrequired | integer | |
resource_ref | string | null | |
created_atrequired | string (date-time) |
{
"data": [
{
"request_id": "01J9Z8Y7X6W5V4U3T2S1R0Q9P8",
"client_request_id": null,
"key_id": "k7m2p9q4r1s8t3u6",
"method": "method",
"route": "POST /v1/orders",
"path": "/v1/orders",
"status": 1,
"error_code": null,
"duration_ms": 42,
"resource_ref": "order:5d0c…",
"created_at": "2026-10-24T09:30:00Z"
}
],
"meta": {
"page": 1,
"per_page": 25,
"total": 1,
"total_pages": 1
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/requests?page=1&per_page=25" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"/v1/requests/{request_id}One request by its id
Parameters
| Name | In | Type | Description |
|---|---|---|---|
request_idrequired | path | string |
Responses
200The request.404No such object in this environment (NOT_FOUND).
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
request_idrequired | string | |
client_request_id | string | null | |
key_id | string | |
methodrequired | string | |
routerequired | string | |
path | string | |
statusrequired | integer | |
error_code | string | null | |
duration_msrequired | integer | |
resource_ref | string | null | |
created_atrequired | string (date-time) |
{
"data": {
"request_id": "01J9Z8Y7X6W5V4U3T2S1R0Q9P8",
"client_request_id": null,
"key_id": "k7m2p9q4r1s8t3u6",
"method": "method",
"route": "POST /v1/orders",
"path": "/v1/orders",
"status": 1,
"error_code": null,
"duration_ms": 42,
"resource_ref": "order:5d0c…",
"created_at": "2026-10-24T09:30:00Z"
}
}200 example
Call it
curl -X GET "https://engine.layercrew.com/v1/requests/01J9Z8Y7X6W5V4U3T2S1R0Q9P8" \
-H "Authorization: Bearer $LAYERCREW_API_KEY"Test mode
Available with test keys only.
/v1/test/orders/{order_id}/advanceMove a test order to its next state
Test keys only. Emits the same events and webhooks a live order would. Allowed moves: pending_review → accepted or rejected; accepted → in_production → ready_to_ship → shipped → delivered; any non-terminal state ↔ on_hold.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
order_idrequired | path | string | The order id (UUID) or number (PA-YYYY-NNNN). |
Request body
| Field | Type | Description |
|---|---|---|
torequired | OrderStatusreceived · pending_review · accepting · accepted · in_production · ready_to_ship · shipped · delivered · on_hold · cancelled · rejected | received: pricing in progress · pending_review: priced, a LayerCrew engineer is looking at it · accepted: in the production queue · in_production · ready_to_ship: passed quality check and packed · shipped: handed to the courier · delivered (final) · on_hold: we need something, see hold · cancelled · rejected, see rejection. |
reason | string | (up to 500 characters) |
{
"to": "received",
"reason": "Cancelled by the customer before production."
}Responses
200Advanced.403Use a test key for this route (TEST_ONLY).404No such object in this environment (NOT_FOUND).409The request conflicts with the current state;error.codesays how (REFERENCE_TAKEN,FILE_IN_USE,FILE_NOT_READY,CANNOT_CANCEL,ENDPOINT_LIMIT,DELIVERY_IN_FLIGHT,IDEMPOTENCY_KEY_REUSED,IDEMPOTENCY_IN_PROGRESS,TERMS_REACCEPTANCE_REQUIRED).
Fields of the 200 response
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
numberrequired | string | |
referencerequired | string | |
environmentrequired | Environmentlive · test | |
statusrequired | OrderStatusreceived · pending_review · accepting · accepted · in_production · ready_to_ship · shipped · delivered · on_hold · cancelled · rejected | received: pricing in progress · pending_review: priced, a LayerCrew engineer is looking at it · accepted: in the production queue · in_production · ready_to_ship: passed quality check and packed · shipped: handed to the courier · delivered (final) · on_hold: we need something, see hold · cancelled · rejected, see rejection. |
pricing_statusrequired | enumpending · priced · failed | |
itemsrequired | array of OrderItem | |
pricingrequired | Pricing | |
payment | Payment | |
deliveryrequired | Delivery | |
white_labelrequired | WhiteLabel | White label is on by default: neutral packaging, no LayerCrew marks on parts, packaging or inserts, no invoice in the box. The courier label names LayerCrew as the shipping account (a courier requirement) and shows your sender name as the contact line; packaging and inserts carry your branding settings. |
metadatarequired | object | |
notes | string | |
shipmentsrequired | array of Shipment | |
invoicesrequired | array of Invoice | |
rejection | Rejection | null | |
hold | Hold | null | |
created_atrequired | string (date-time) | |
updated_atrequired | string (date-time) | |
accepted_at | string (date-time) | null | |
shipped_at | string (date-time) | null | |
delivered_at | string (date-time) | null | |
cancelled_at | string (date-time) | null | |
linksrequired | object |
{
"data": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "PA-2026-0007",
"reference": "SHOP-10231",
"environment": "live",
"status": "received",
"pricing_status": "pending",
"items": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"position": 1,
"file": {
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"filename": "bracket-v3.stl",
"format": "stl"
},
"quantity": 2,
"material": "PLA",
"colour": "black",
"nozzle": "0.4",
"notes": "Fit check before the batch, please.",
"pricing_status": "pending",
"list_unit_price": "12.40",
"discount_pct": "0",
"unit_price": "12.40",
"line_total": "12.40",
"estimate": {
"weight_grams": 31.2,
"time_seconds": 5400,
"unit_yield": 1,
"printer_model": "Bambu Lab A2L",
"nozzle": "0.4",
"material": "PLA",
"infill_pct": 15,
"wall_loops": 3,
"support": "auto",
"warnings": [
"warnings"
],
"priced_at": "2026-10-24T09:30:00Z"
},
"failure_code": null,
"failure_message": null
}
],
"pricing": {
"currency": "EUR",
"subtotal": "12.40",
"discount_total": "12.40",
"shipping_total": "12.40",
"tax_total": "12.40",
"tax_treatment": "standard",
"grand_total": "12.40",
"final": true
},
"payment": {
"method": "bank_transfer",
"status": "unpaid",
"ship_before_payment": false,
"amount_due": "12.40",
"instructions": {
"beneficiary": "LAYER CREW SRL",
"iban": "RO49AAAA1B31007593840000",
"bank": "Example Bank",
"reference": "SHOP-10231"
},
"paid_at": "2026-10-24T09:30:00Z"
},
"delivery": {
"name": "Claire Martin",
"company": "Atelier Martin",
"phone": "+33 6 12 34 56 78",
"email": "claire@example.com",
"line1": "12 rue de la Paix",
"line2": "Bâtiment B",
"city": "Lyon",
"region": "Auvergne-Rhône-Alpes",
"postal_code": "69001",
"country_code": "FR"
},
"white_label": {
"enabled": true,
"sender_name": "Studio NS",
"card_text": "Thank you for your order — Studio NS",
"packaging_preset": "neutral",
"no_invoice_in_box": true,
"language": "fr"
},
"metadata": {
"shop_order_id": "10231"
},
"notes": "Fit check before the batch, please.",
"shipments": [
{
"carrier": "FAN Courier",
"tracking_number": "2057100012345",
"tracking_url": "https://www.fancourier.ro/awb-tracking/?awb=2057100012345",
"status": "shipped",
"last_tracking_status": "last tracking status",
"shipped_at": "2026-10-24T09:30:00Z",
"delivered_at": "2026-10-24T09:30:00Z"
}
],
"invoices": [
{
"id": "4f1b2c3d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"number": "number",
"kind": "fiscal",
"issued_at": "2026-10-24T09:30:00Z"
}
],
"rejection": null,
"hold": null,
"created_at": "2026-10-24T09:30:00Z",
"updated_at": "2026-10-24T09:30:00Z",
"accepted_at": "2026-10-24T09:30:00Z",
"shipped_at": "2026-10-24T09:30:00Z",
"delivered_at": "2026-10-24T09:30:00Z",
"cancelled_at": "2026-10-24T09:30:00Z",
"links": {
"self": "self",
"events": "events"
}
}
}200 example
Call it
curl -X POST "https://engine.layercrew.com/v1/test/orders/PA-2026-0007/advance" \
-H "Authorization: Bearer $LAYERCREW_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "received",
"reason": "Cancelled by the customer before production."
}'