Documentation
Partner API

API reference

Every endpoint of the LayerCrew Partner API, grouped by tag with parameters, request and response fields and examples, generated from the OpenAPI document.

Updated 2026-10-24MarkdownOpenAPI

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 page and per_page (25 by default, 100 at most) and return newest first. Event feeds take after (a seq) and limit (50 by default, 200 at most) and return oldest first.
  • Every response carries X-Request-ID. Rate-limited responses carry Retry-After, X-RateLimit-Limit and X-RateLimit-Remaining.
  • Request bodies are JSON up to 256 KiB. POST /v1/orders requires an Idempotency-Key; other creates accept one.
  • The API version is 2026-10-24; every event carries it as api_version.

Account

Who you are, your plan and your usage.

get/v1/ping

Check 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). Honour Retry-After.
Fields of the 200 response
Fields of the 200 response
FieldTypeDescription
partnerrequiredobject
environmentrequiredEnvironmentlive · test
key_idrequiredstring
planrequiredobject
rate_limitrequiredobject
server_timerequiredstring (date-time)
JSON
{
  "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"
get/v1/account

Your 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). Honour Retry-After.
Fields of the 200 response
Fields of the 200 response
FieldTypeDescription
partnerrequiredobject
statusrequiredenumpending_verification · pending_agreement · active · suspended · closed
planrequiredobject
limitsrequiredPlanLimitsThe limits in force for you (plan plus any agreed overrides).
usagerequiredobject
agreementsrequiredarray of object
JSON
{
  "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"
get/v1/openapi.jsonno key needed

This document

Responses

  • 200The OpenAPI 3.1 description of this API.
JSON
{}

200 example

Call it

curl -X GET "https://engine.layercrew.com/v1/openapi.json"

Materials

What you can order parts in.

get/v1/materials

Materials, 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)
Fields of the 200 response
FieldTypeDescription
materialrequiredstring
descriptionstring
nozzlesrequiredarray of string
coloursrequiredarray of object
JSON
{
  "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.

get/v1/files

List your files

Parameters

NameInTypeDescription
pagequeryinteger
per_pagequeryinteger
statusqueryFileStatus

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)
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
filenamerequiredstring
formatrequiredFileFormatstl · obj · 3mf
statusrequiredFileStatuspending · ready · rejected · purged
size_bytesrequiredinteger
sha256string
rejection_codeenum | nullsize_mismatch · hash_mismatch · not_a_model · too_complex · too_large · upload_missing
factsobjectWhat we read from the file: triangles, bounding box in mm, object count, producer.
created_atrequiredstring (date-time)
ready_atstring (date-time) | null
purge_afterstring (date-time) | nullWhen the file will be deleted unless an order uses it.
JSON
{
  "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"
post/v1/files

Start 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

Request body fields
FieldTypeDescription
filenamerequiredstringWith its extension: .stl, .obj or .3mf. (up to 200 characters)
size_bytesrequiredinteger(at least 1)
sha256requiredstringLowercase hex SHA-256 of the exact bytes you will upload.
content_typestring(default "application/octet-stream")
JSON
{
  "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.details maps 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). Honour Retry-After.
Fields of the 201 response
Fields of the 201 response
FieldTypeDescription
idrequiredstring (uuid)
filenamerequiredstring
formatrequiredFileFormatstl · obj · 3mf
statusrequiredFileStatuspending · ready · rejected · purged
size_bytesrequiredinteger
sha256string
rejection_codeenum | nullsize_mismatch · hash_mismatch · not_a_model · too_complex · too_large · upload_missing
factsobjectWhat we read from the file: triangles, bounding box in mm, object count, producer.
created_atrequiredstring (date-time)
ready_atstring (date-time) | null
purge_afterstring (date-time) | nullWhen the file will be deleted unless an order uses it.
uploadrequiredobject
JSON
{
  "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"
}'
get/v1/files/{file_id}

Get a file

Parameters

NameInTypeDescription
file_idrequiredpathstring (uuid)

Responses

  • 200The file.
  • 404No such object in this environment (NOT_FOUND).
Fields of the 200 response
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
filenamerequiredstring
formatrequiredFileFormatstl · obj · 3mf
statusrequiredFileStatuspending · ready · rejected · purged
size_bytesrequiredinteger
sha256string
rejection_codeenum | nullsize_mismatch · hash_mismatch · not_a_model · too_complex · too_large · upload_missing
factsobjectWhat we read from the file: triangles, bounding box in mm, object count, producer.
created_atrequiredstring (date-time)
ready_atstring (date-time) | null
purge_afterstring (date-time) | nullWhen the file will be deleted unless an order uses it.
JSON
{
  "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"
delete/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

NameInTypeDescription
file_idrequiredpathstring (uuid)

Responses

  • 202Scheduled for deletion.
  • 204Deleted.
  • 404No such object in this environment (NOT_FOUND).
  • 409The request conflicts with the current state; error.code says 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"
post/v1/files/{file_id}/complete

Finish 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

NameInTypeDescription
file_idrequiredpathstring (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_code says why.
Fields of the 200 response
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
filenamerequiredstring
formatrequiredFileFormatstl · obj · 3mf
statusrequiredFileStatuspending · ready · rejected · purged
size_bytesrequiredinteger
sha256string
rejection_codeenum | nullsize_mismatch · hash_mismatch · not_a_model · too_complex · too_large · upload_missing
factsobjectWhat we read from the file: triangles, bounding box in mm, object count, producer.
created_atrequiredstring (date-time)
ready_atstring (date-time) | null
purge_afterstring (date-time) | nullWhen the file will be deleted unless an order uses it.
JSON
{
  "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.

get/v1/quotes

List your quotes

Parameters

NameInTypeDescription
pagequeryinteger
per_pagequeryinteger

Responses

  • 200Quotes, newest first.
Fields of the 200 response (each item of data)
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
file_idrequiredstring (uuid)
materialrequiredstring
nozzlerequiredstring
quantityrequiredinteger
statusrequiredenumpending · priced · failed
unit_priceMoneyEUR with two decimals, as a string.
list_unit_priceMoneyEUR with two decimals, as a string.
discount_pctstring
totalMoneyEUR with two decimals, as a string.
currencyenumEUR
tiersarray of objectUnit price at other quantities.
estimatePriceEstimateWhat the slicer measured and the settings it used.
failure_codeenum | nullmodel_too_large · not_a_model · material_unavailable · slicer_rejected · file_unavailable
failure_messagestring | null
created_atrequiredstring (date-time)
priced_atstring (date-time) | null
JSON
{
  "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"
post/v1/quotes

Price 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

Request body fields
FieldTypeDescription
file_idrequiredstring (uuid)
materialrequiredstring
nozzlestring(default "0.4")
quantityrequiredinteger(at least 1)
JSON
{
  "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.code says 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.details maps 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). Honour Retry-After.
Fields of the 202 response
Fields of the 202 response
FieldTypeDescription
idrequiredstring (uuid)
file_idrequiredstring (uuid)
materialrequiredstring
nozzlerequiredstring
quantityrequiredinteger
statusrequiredenumpending · priced · failed
unit_priceMoneyEUR with two decimals, as a string.
list_unit_priceMoneyEUR with two decimals, as a string.
discount_pctstring
totalMoneyEUR with two decimals, as a string.
currencyenumEUR
tiersarray of objectUnit price at other quantities.
estimatePriceEstimateWhat the slicer measured and the settings it used.
failure_codeenum | nullmodel_too_large · not_a_model · material_unavailable · slicer_rejected · file_unavailable
failure_messagestring | null
created_atrequiredstring (date-time)
priced_atstring (date-time) | null
JSON
{
  "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
}'
get/v1/quotes/{quote_id}

Get a quote

Parameters

NameInTypeDescription
quote_idrequiredpathstring (uuid)

Responses

  • 200The quote.
  • 404No such object in this environment (NOT_FOUND).
Fields of the 200 response
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
file_idrequiredstring (uuid)
materialrequiredstring
nozzlerequiredstring
quantityrequiredinteger
statusrequiredenumpending · priced · failed
unit_priceMoneyEUR with two decimals, as a string.
list_unit_priceMoneyEUR with two decimals, as a string.
discount_pctstring
totalMoneyEUR with two decimals, as a string.
currencyenumEUR
tiersarray of objectUnit price at other quantities.
estimatePriceEstimateWhat the slicer measured and the settings it used.
failure_codeenum | nullmodel_too_large · not_a_model · material_unavailable · slicer_rejected · file_unavailable
failure_messagestring | null
created_atrequiredstring (date-time)
priced_atstring (date-time) | null
JSON
{
  "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.

get/v1/orders

List your orders

Parameters

NameInTypeDescription
pagequeryinteger
per_pagequeryinteger
statusqueryOrderStatus
referencequerystringExact match on your reference.
created_afterquerystring (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)
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
numberrequiredstring
referencerequiredstring
environmentrequiredEnvironmentlive · test
statusrequiredOrderStatusreceived · pending_review · accepting · accepted · in_production · ready_to_ship · shipped · delivered · on_hold · cancelled · rejectedreceived: 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_statusrequiredenumpending · priced · failed
itemsrequiredarray of OrderItem
pricingrequiredPricing
paymentPayment
deliveryrequiredDelivery
white_labelrequiredWhiteLabelWhite 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.
metadatarequiredobject
notesstring
shipmentsrequiredarray of Shipment
invoicesrequiredarray of Invoice
rejectionRejection | null
holdHold | null
created_atrequiredstring (date-time)
updated_atrequiredstring (date-time)
accepted_atstring (date-time) | null
shipped_atstring (date-time) | null
delivered_atstring (date-time) | null
cancelled_atstring (date-time) | null
linksrequiredobject
JSON
{
  "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"
post/v1/orders

Create 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

NameInTypeDescription
Idempotency-KeyrequiredheaderstringUnique per attempt, up to 255 characters of [A-Za-z0-9._:~-]. Kept 24 hours.

Request body

Request body fields
FieldTypeDescription
referencerequiredstringYour own order reference; unique per environment. (up to 120 characters)
itemsrequiredarray of OrderItemCreate
deliveryrequiredDelivery
white_labelWhiteLabelWhite 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.
notesstring(up to 2000 characters)
metadataobjectReturned untouched on the order and in every webhook. (up to 20 keys)
JSON
{
  "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 same Idempotency-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.code says 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.details maps 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). Honour Retry-After.
Fields of the 200 response
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
numberrequiredstring
referencerequiredstring
environmentrequiredEnvironmentlive · test
statusrequiredOrderStatusreceived · pending_review · accepting · accepted · in_production · ready_to_ship · shipped · delivered · on_hold · cancelled · rejectedreceived: 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_statusrequiredenumpending · priced · failed
itemsrequiredarray of OrderItem
pricingrequiredPricing
paymentPayment
deliveryrequiredDelivery
white_labelrequiredWhiteLabelWhite 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.
metadatarequiredobject
notesstring
shipmentsrequiredarray of Shipment
invoicesrequiredarray of Invoice
rejectionRejection | null
holdHold | null
created_atrequiredstring (date-time)
updated_atrequiredstring (date-time)
accepted_atstring (date-time) | null
shipped_atstring (date-time) | null
delivered_atstring (date-time) | null
cancelled_atstring (date-time) | null
linksrequiredobject
JSON
{
  "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"
  }
}'
get/v1/orders/{order_id}

Get an order

order_id is the order's id or its number (PA-2026-0007).

Parameters

NameInTypeDescription
order_idrequiredpathstringThe order id (UUID) or number (PA-YYYY-NNNN).

Responses

  • 200The order.
  • 404No such object in this environment (NOT_FOUND).
Fields of the 200 response
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
numberrequiredstring
referencerequiredstring
environmentrequiredEnvironmentlive · test
statusrequiredOrderStatusreceived · pending_review · accepting · accepted · in_production · ready_to_ship · shipped · delivered · on_hold · cancelled · rejectedreceived: 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_statusrequiredenumpending · priced · failed
itemsrequiredarray of OrderItem
pricingrequiredPricing
paymentPayment
deliveryrequiredDelivery
white_labelrequiredWhiteLabelWhite 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.
metadatarequiredobject
notesstring
shipmentsrequiredarray of Shipment
invoicesrequiredarray of Invoice
rejectionRejection | null
holdHold | null
created_atrequiredstring (date-time)
updated_atrequiredstring (date-time)
accepted_atstring (date-time) | null
shipped_atstring (date-time) | null
delivered_atstring (date-time) | null
cancelled_atstring (date-time) | null
linksrequiredobject
JSON
{
  "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"
get/v1/orders/{order_id}/events

The order's events, in order

Parameters

NameInTypeDescription
order_idrequiredpathstringThe order id (UUID) or number (PA-YYYY-NNNN).
afterqueryintegerReturn events with seq greater than this.
limitqueryinteger

Responses

  • 200Events, oldest first.
  • 404No such object in this environment (NOT_FOUND).
Fields of the 200 response (each item of data)
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
typerequiredEventTypeorder.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_versionrequiredstring
created_atrequiredstring (date-time)
seqrequiredintegerPer-partner, gap-free, strictly increasing.
environmentrequiredEnvironmentlive · test
reason_codestring | null
datarequiredobjectorder 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.
JSON
{
  "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"
post/v1/orders/{order_id}/cancel

Cancel 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

NameInTypeDescription
order_idrequiredpathstringThe order id (UUID) or number (PA-YYYY-NNNN).

Request body (optional)

Request body fields
FieldTypeDescription
reasonstring(up to 500 characters)
JSON
{
  "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.code says 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
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
numberrequiredstring
referencerequiredstring
environmentrequiredEnvironmentlive · test
statusrequiredOrderStatusreceived · pending_review · accepting · accepted · in_production · ready_to_ship · shipped · delivered · on_hold · cancelled · rejectedreceived: 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_statusrequiredenumpending · priced · failed
itemsrequiredarray of OrderItem
pricingrequiredPricing
paymentPayment
deliveryrequiredDelivery
white_labelrequiredWhiteLabelWhite 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.
metadatarequiredobject
notesstring
shipmentsrequiredarray of Shipment
invoicesrequiredarray of Invoice
rejectionRejection | null
holdHold | null
created_atrequiredstring (date-time)
updated_atrequiredstring (date-time)
accepted_atstring (date-time) | null
shipped_atstring (date-time) | null
delivered_atstring (date-time) | null
cancelled_atstring (date-time) | null
linksrequiredobject
JSON
{
  "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."
}'
get/v1/orders/{order_id}/invoices

Invoices issued for the order

Parameters

NameInTypeDescription
order_idrequiredpathstringThe 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)
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
numberrequiredstring
kindrequiredenumfiscal · proforma · storno
issued_atrequiredstring (date-time)
JSON
{
  "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"
get/v1/orders/{order_id}/invoices/{invoice_id}/download-url

A 15-minute link to the invoice PDF

Parameters

NameInTypeDescription
order_idrequiredpathstringThe order id (UUID) or number (PA-YYYY-NNNN).
invoice_idrequiredpathstring (uuid)

Responses

  • 200The link.
  • 404No such object in this environment (NOT_FOUND).
Fields of the 200 response
Fields of the 200 response
FieldTypeDescription
urlrequiredstring (uri)
expires_atrequiredstring (date-time)
JSON
{
  "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"
delete/v1/orders/{order_id}/recipient

Erase 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

NameInTypeDescription
order_idrequiredpathstringThe 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.code says 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.

get/v1/events

Everything 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

NameInTypeDescription
afterqueryintegerReturn events with seq greater than this.
limitqueryinteger
typesquerystringComma-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)
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
typerequiredEventTypeorder.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_versionrequiredstring
created_atrequiredstring (date-time)
seqrequiredintegerPer-partner, gap-free, strictly increasing.
environmentrequiredEnvironmentlive · test
reason_codestring | null
datarequiredobjectorder 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.
JSON
{
  "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.

get/v1/webhook-endpoints

List endpoints

Responses

  • 200Endpoints.
Fields of the 200 response (each item of data)
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
urlrequiredstring
descriptionstring
environmentrequiredEnvironmentlive · test
event_typesrequiredarray of string | null
enabledrequiredboolean
disabled_reasonstring | null
consecutive_failuresinteger
last_success_atstring (date-time) | null
secret_rotated_atstring (date-time) | null
created_atrequiredstring (date-time)
JSON
{
  "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"
post/v1/webhook-endpoints

Register 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

Request body fields
FieldTypeDescription
urlrequiredstring (uri)(up to 500 characters)
descriptionstring(up to 200 characters)
event_typesarray of EventType | nullnull = every event.
JSON
{
  "url": "https://shop.example.com/webhooks/layercrew",
  "description": "Production events",
  "event_types": [
    "order.received"
  ]
}

Responses

  • 201Created; secret is shown once.
  • 409The request conflicts with the current state; error.code says 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.details maps field names to messages (VALIDATION_ERROR, IDEMPOTENCY_KEY_REQUIRED, MATERIAL_UNAVAILABLE, FILE_REJECTED, ENDPOINT_URL_INVALID).
Fields of the 201 response
Fields of the 201 response
FieldTypeDescription
idrequiredstring (uuid)
urlrequiredstring
descriptionstring
environmentrequiredEnvironmentlive · test
event_typesrequiredarray of string | null
enabledrequiredboolean
disabled_reasonstring | null
consecutive_failuresinteger
last_success_atstring (date-time) | null
secret_rotated_atstring (date-time) | null
created_atrequiredstring (date-time)
secretrequiredstringwhsec_ + base64. Shown once.
JSON
{
  "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"
  ]
}'
get/v1/webhook-endpoints/{endpoint_id}

Get an endpoint

Parameters

NameInTypeDescription
endpoint_idrequiredpathstring (uuid)

Responses

  • 200The endpoint.
  • 404No such object in this environment (NOT_FOUND).
Fields of the 200 response
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
urlrequiredstring
descriptionstring
environmentrequiredEnvironmentlive · test
event_typesrequiredarray of string | null
enabledrequiredboolean
disabled_reasonstring | null
consecutive_failuresinteger
last_success_atstring (date-time) | null
secret_rotated_atstring (date-time) | null
created_atrequiredstring (date-time)
JSON
{
  "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"
patch/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

NameInTypeDescription
endpoint_idrequiredpathstring (uuid)

Request body

Request body fields
FieldTypeDescription
urlstring (uri)
descriptionstring
event_typesarray of EventType | null
enabledboolean
JSON
{
  "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.details maps field names to messages (VALIDATION_ERROR, IDEMPOTENCY_KEY_REQUIRED, MATERIAL_UNAVAILABLE, FILE_REJECTED, ENDPOINT_URL_INVALID).
Fields of the 200 response
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
urlrequiredstring
descriptionstring
environmentrequiredEnvironmentlive · test
event_typesrequiredarray of string | null
enabledrequiredboolean
disabled_reasonstring | null
consecutive_failuresinteger
last_success_atstring (date-time) | null
secret_rotated_atstring (date-time) | null
created_atrequiredstring (date-time)
JSON
{
  "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
}'
delete/v1/webhook-endpoints/{endpoint_id}

Delete an endpoint

Parameters

NameInTypeDescription
endpoint_idrequiredpathstring (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"
post/v1/webhook-endpoints/{endpoint_id}/rotate-secret

Rotate 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

NameInTypeDescription
endpoint_idrequiredpathstring (uuid)

Responses

  • 200Rotated.
  • 404No such object in this environment (NOT_FOUND).
Fields of the 200 response
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
urlrequiredstring
descriptionstring
environmentrequiredEnvironmentlive · test
event_typesrequiredarray of string | null
enabledrequiredboolean
disabled_reasonstring | null
consecutive_failuresinteger
last_success_atstring (date-time) | null
secret_rotated_atstring (date-time) | null
created_atrequiredstring (date-time)
secretrequiredstringwhsec_ + base64. Shown once.
JSON
{
  "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"
post/v1/webhook-endpoints/{endpoint_id}/ping

Send a signed test event

Queues a test.ping delivery so you can verify your signature check before going live.

Parameters

NameInTypeDescription
endpoint_idrequiredpathstring (uuid)

Responses

  • 202Queued.
  • 404No such object in this environment (NOT_FOUND).
Fields of the 202 response
Fields of the 202 response
FieldTypeDescription
idrequiredstring (uuid)
endpoint_idrequiredstring (uuid)
event_idrequiredstring (uuid)
event_typerequiredstring
seqrequiredinteger
statusrequiredDeliveryStatuspending · in_flight · delivered · failed · skipped
attemptsrequiredinteger
max_attemptsinteger
next_attempt_atstring (date-time) | null
last_status_codeinteger | null
last_errorstring | null
delivered_atstring (date-time) | null
created_atrequiredstring (date-time)
JSON
{
  "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"
get/v1/webhook-deliveries

Delivery log

Parameters

NameInTypeDescription
pagequeryinteger
per_pagequeryinteger
endpoint_idquerystring (uuid)
statusqueryDeliveryStatus
event_idquerystring (uuid)

Responses

  • 200Deliveries, newest first.
Fields of the 200 response (each item of data)
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
endpoint_idrequiredstring (uuid)
event_idrequiredstring (uuid)
event_typerequiredstring
seqrequiredinteger
statusrequiredDeliveryStatuspending · in_flight · delivered · failed · skipped
attemptsrequiredinteger
max_attemptsinteger
next_attempt_atstring (date-time) | null
last_status_codeinteger | null
last_errorstring | null
delivered_atstring (date-time) | null
created_atrequiredstring (date-time)
JSON
{
  "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"
get/v1/webhook-deliveries/{delivery_id}

A delivery with every attempt

Parameters

NameInTypeDescription
delivery_idrequiredpathstring (uuid)

Responses

  • 200The delivery.
  • 404No such object in this environment (NOT_FOUND).
Fields of the 200 response
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
endpoint_idrequiredstring (uuid)
event_idrequiredstring (uuid)
event_typerequiredstring
seqrequiredinteger
statusrequiredDeliveryStatuspending · in_flight · delivered · failed · skipped
attemptsrequiredinteger
max_attemptsinteger
next_attempt_atstring (date-time) | null
last_status_codeinteger | null
last_errorstring | null
delivered_atstring (date-time) | null
created_atrequiredstring (date-time)
attempts_logrequiredarray of WebhookAttempt
eventrequiredEvent
JSON
{
  "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"
post/v1/webhook-deliveries/{delivery_id}/redeliver

Send 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

NameInTypeDescription
delivery_idrequiredpathstring (uuid)

Responses

  • 202Queued.
  • 404No such object in this environment (NOT_FOUND).
  • 409The request conflicts with the current state; error.code says 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
Fields of the 202 response
FieldTypeDescription
idrequiredstring (uuid)
endpoint_idrequiredstring (uuid)
event_idrequiredstring (uuid)
event_typerequiredstring
seqrequiredinteger
statusrequiredDeliveryStatuspending · in_flight · delivered · failed · skipped
attemptsrequiredinteger
max_attemptsinteger
next_attempt_atstring (date-time) | null
last_status_codeinteger | null
last_errorstring | null
delivered_atstring (date-time) | null
created_atrequiredstring (date-time)
JSON
{
  "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.

get/v1/requests

Your 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

NameInTypeDescription
pagequeryinteger
per_pagequeryinteger
fromquerystring (date-time)
toquerystring (date-time)
statusqueryinteger
routequerystring

Responses

  • 200Requests, newest first.
Fields of the 200 response (each item of data)
Fields of the 200 response
FieldTypeDescription
request_idrequiredstring
client_request_idstring | null
key_idstring
methodrequiredstring
routerequiredstring
pathstring
statusrequiredinteger
error_codestring | null
duration_msrequiredinteger
resource_refstring | null
created_atrequiredstring (date-time)
JSON
{
  "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"
get/v1/requests/{request_id}

One request by its id

Parameters

NameInTypeDescription
request_idrequiredpathstring

Responses

  • 200The request.
  • 404No such object in this environment (NOT_FOUND).
Fields of the 200 response
Fields of the 200 response
FieldTypeDescription
request_idrequiredstring
client_request_idstring | null
key_idstring
methodrequiredstring
routerequiredstring
pathstring
statusrequiredinteger
error_codestring | null
duration_msrequiredinteger
resource_refstring | null
created_atrequiredstring (date-time)
JSON
{
  "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.

post/v1/test/orders/{order_id}/advance

Move 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

NameInTypeDescription
order_idrequiredpathstringThe order id (UUID) or number (PA-YYYY-NNNN).

Request body

Request body fields
FieldTypeDescription
torequiredOrderStatusreceived · pending_review · accepting · accepted · in_production · ready_to_ship · shipped · delivered · on_hold · cancelled · rejectedreceived: 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.
reasonstring(up to 500 characters)
JSON
{
  "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.code says 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
Fields of the 200 response
FieldTypeDescription
idrequiredstring (uuid)
numberrequiredstring
referencerequiredstring
environmentrequiredEnvironmentlive · test
statusrequiredOrderStatusreceived · pending_review · accepting · accepted · in_production · ready_to_ship · shipped · delivered · on_hold · cancelled · rejectedreceived: 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_statusrequiredenumpending · priced · failed
itemsrequiredarray of OrderItem
pricingrequiredPricing
paymentPayment
deliveryrequiredDelivery
white_labelrequiredWhiteLabelWhite 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.
metadatarequiredobject
notesstring
shipmentsrequiredarray of Shipment
invoicesrequiredarray of Invoice
rejectionRejection | null
holdHold | null
created_atrequiredstring (date-time)
updated_atrequiredstring (date-time)
accepted_atstring (date-time) | null
shipped_atstring (date-time) | null
delivered_atstring (date-time) | null
cancelled_atstring (date-time) | null
linksrequiredobject
JSON
{
  "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."
}'

We value your privacy

We use cookies for analytics and advertising to improve your experience and measure our marketing. See our Privacy Policy.