Quotes

View as Markdown

Prices for printing model files. Integrators only.

The quote object

A price for printing one model file. Integrators upload model files to get quotes; until the account is approved, 10 approved quotes are also what 3DAPI reviews to approve the account (see get_integrator_onboarding).

Attributes

  • idstring

    Unique identifier of the quote, prefixed with qte_. Treat it as an opaque string: store it and compare it, never parse it.

  • objectstring

    Names the type of this object. Always quote.

  • namestring

    Display name of the quote. The name you sent when creating it, otherwise the uploaded file name.

  • fileobject

    The model file you uploaded, exactly as you sent it, and the production version 3DAPI prepared from it.

  • statusQuoteStatus

    Where the quote stands:

    • processing: the file is being sliced to measure material and print time. Usually takes one to a few minutes.
    • ready: slicing finished and price is set.
    • failed: the file could not be sliced, for example a broken or empty model. failure_reason says why. Upload a corrected file as a new quote.
    Possible valuesprocessingreadyfailed
  • priceobject or null

    Price to print one unit of the model, in usd: the price of the file that gets printed, which is file.production_version when there is one, otherwise your upload. Null until status is ready, and on failed quotes.

  • failure_reasonstring or null

    Why slicing failed, written to be shown to a person, usually with how to fix the file. For example, a binary STL the slicer cannot read (small models exported with zero normals are mistaken for text STL files) says to export it again with normals or as .3mf. Null unless status is failed. What a printable file needs: https://public-api.dapi.digital/docs/guides/file-requirements.

  • suggested_materialsarray of SuggestedMaterial or null

    One suggested catalog material per extruder slot the file prints with, in slot order, read from the colours and filament types in your file. Only slots something prints with are listed, so the numbers can have gaps (a project using filaments 2 and 4 lists slots 2 and 4).

    Order with use_suggested_materials: true on the order line to print with exactly these, or send materials as [{ slot, material }] for the same slots to choose your own.

    Null until status is ready, on failed quotes, and on quotes created before suggestions existed.

  • approvalobject

    The file in your account approval. Approval only matters until your account is approved; afterwards new quotes stay not_submitted and are not reviewed one by one: an order goes to production once its quote is ready.

  • created_attimestamp

    Point in time, ISO 8601 in UTC.

  • finished_attimestamp or null

    When slicing finished, successfully or not. Null while processing.

The quote object
{
  ,
  ,
  ,
  ,
  ,
  ,
  ,
  ,
  ,
  ,
  
}

List quotes

GET/v2/quotes

Credentials
An API key with the quotes:read scope (full access includes every scope). A signed-in dashboard session works too.
For
Integrators
Operation id
list_quotes

Lists your quotes, newest first, with their price and approval status. Use the filters to find quotes to submit for approval (status=ready&approval_status=not_submitted). Integrators only; designers are refused with actor_not_allowed.

Query parameters

  • statusarray of QuoteStatus

    Only quotes in these states. Repeat for several.

    Possible valuesprocessingreadyfailed
  • approval_statusarray of QuoteApprovalStatus

    Only quotes in these approval states, for example approval_status=not_submitted&status=ready for the quotes you can still submit for approval.

    Possible valuesnot_submittedin_reviewapprovedrejected
  • created_aftertimestamp

    Only quotes created at or after this time (ISO 8601).

  • created_beforetimestamp

    Only quotes created before this time (ISO 8601).

  • limitinteger

    How many results per page, from 1 to 100.

    Range 1 to 100. Defaults to 20.
  • cursorstring

    Where to continue from: the next_cursor of the previous page. Omit for the first page.

Returns200 OK

A page of quotes.

Responses

  • 200

    A page of quotes.

  • 400

    The request is invalid. details.errors lists each problem (validation_failed), or an expand[] path is unknown (invalid_expand).

  • 401

    Credentials are missing (missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials).

  • 403

    The credentials are valid but not allowed to do this: a scope is missing (missing_scope), the endpoint is for another kind of account (actor_not_allowed) or another kind of credential (credential_not_allowed), the account may no longer use the API (account_blacklisted), or the account must change something first, in which case details.fix_url links to the dashboard page that fixes it.

  • 429

    Too many requests (rate_limited): the limit is 500 per minute per API key (or signed-in user). Wait for the number of seconds in the Retry-After header, then retry; details has limit, window_seconds, reset_at and retry_after_seconds.

Errors use the error object.

GET/v2/quotes
curl "https://public-api.dapi.digital/v2/quotes" \
  -H "x-api-key: $DAPI_API_KEY"
Response
{
  "object": "list",
  "data": [
    {
      "id": "qte_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
      "object": "quote",
      "name": "Phone stand v2",
      "file": {
        "name": "phone-stand-v2.3mf",
        "size_bytes": 2758723,
        "download_url": "https://files.example.com/public-api/quotes/7f3a/input/phone-stand-v2.3mf?signature=abc",
        "production_version": {
          "name": "phone-stand-v2.3mf",
          "format": "3mf",
          "size_bytes": 2913004,
          "download_url": "https://files.example.com/public-api/quotes/7f3a/production/phone-stand-v2.3mf?signature=def",
          "prepared_at": "2026-10-20T09:12:09Z"
        }
      },
      "status": "ready",
      "suggested_materials": [
        {
          "slot": 1,
          "file_color": "#C12E1F",
          "file_filament_type": "PLA",
          "material": {
            "id": "mat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
            "object": "material",
            "name": "PLA Red",
            "custom": false
          },
          "match": "exact"
        },
        {
          "slot": 3,
          "file_color": "#0B2A88",
          "file_filament_type": null,
          "material": {
            "id": "mat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
            "object": "material",
            "name": "PLA Blue",
            "custom": false
          },
          "match": "close"
        }
      ],
      "price": {
        "amount": 1245,
        "currency": "usd"
      },
      "failure_reason": null,
      "approval": {
        "status": "not_submitted",
        "reason": null
      },
      "created_at": "2026-10-20T09:12:00Z",
      "finished_at": "2026-10-20T09:13:41Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Quote a model file

POST/v2/quotes

Credentials
An API key with the quotes:write scope (full access includes every scope). A signed-in dashboard session works too.
For
Integrators
Operation id
create_quote

Starts pricing one model file and returns the quote with status: processing. Poll get_quote until it is ready (with price) or failed.

While it is processing, 3DAPI first checks the file against its production printers and, when needed, prepares a production version with the right printer, process and filament settings (file.production_version). The price is for that version, since it is the file that gets printed; your upload stays downloadable as it is.

Upload the file first: POST /v2/uploads with purpose quote_file, PUT the bytes, then send the upload id here.

Limits before your account is approved: up to 25 quotes per round, and none while an approval request is in review. After a review that rejected files you get a fresh round of 25. Once approved, quotes are unlimited. A quote counts from the moment it is created, while it is processing and once it is ready; a quote that ends failed is given back to your allowance. get_integrator_onboarding shows how many you have used.

Integrators only; designers are refused with actor_not_allowed.

Headers

  • Idempotency-Keystring

    Any unique string, for example a UUID. Sending the same request again with the same key within 24 hours returns the first response without doing anything twice. Reusing a key with a different body is refused with idempotency_key_reused. A refused request (4xx) frees the key so you can correct and resend it; a server error (5xx) is kept and returned again, because the write may already have happened: check the resource before retrying with a new key.

Request body

  • fileobjectRequired

    The model to quote, as { "upload": "upl_..." } from POST /v2/uploads with purpose quote_file.

  • namestring

    Display name for the quote. Defaults to the uploaded file name.

Returns201 Created

The quote, being processed. Returns the quote object.

Responses

  • 201

    The quote, being processed.

  • 400

    The request is invalid (validation_failed).

  • 401

    Credentials are missing (missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials).

  • 403

    The credentials are valid but not allowed to do this: a scope is missing (missing_scope), the endpoint is for another kind of account (actor_not_allowed) or another kind of credential (credential_not_allowed), the account may no longer use the API (account_blacklisted), or the account must change something first, in which case details.fix_url links to the dashboard page that fixes it.

  • 409

    Your account cannot quote right now: you used the 25 uploads of this round, so request approval next (upload_limit_reached), or an approval request is in review and uploads resume once it is reviewed (approval_in_review).

  • 422

    The upload is unknown, expired or of the wrong purpose (unknown_upload, upload_expired, upload_purpose_mismatch), its file was never sent to upload_url (upload_missing), or the upload id was already used by another quote (upload_already_used; every upload id works once).

  • 429

    The daily quote limit for accounts not yet approved is reached (daily_quote_limit_reached). It resets at midnight UTC. Too many requests (rate_limited): the limit is 500 per minute per API key (or signed-in user), plus 60 per minute per API key (or signed-in user) for quote, upload, order and payment operations. Wait for the number of seconds in the Retry-After header, then retry; details has limit, window_seconds, reset_at and retry_after_seconds.

Errors use the error object.

POST/v2/quotes
curl -X POST "https://public-api.dapi.digital/v2/quotes" \
  -H "x-api-key: $DAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "file": {
    "upload": "upl_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu"
  },
  "name": "Phone stand v2"
}'
Response
{
  "id": "qte_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
  "object": "quote",
  "name": "Phone stand v2",
  "file": {
    "name": "phone-stand-v2.3mf",
    "size_bytes": 2758723,
    "download_url": "https://files.example.com/public-api/quotes/7f3a/input/phone-stand-v2.3mf?signature=abc",
    "production_version": null
  },
  "status": "processing",
  "suggested_materials": null,
  "price": null,
  "failure_reason": null,
  "approval": {
    "status": "not_submitted",
    "reason": null
  },
  "created_at": "2026-10-20T09:12:00Z",
  "finished_at": null
}

Get a quote

GET/v2/quotes/{id}

Credentials
An API key with the quotes:read scope (full access includes every scope). A signed-in dashboard session works too.
For
Integrators
Operation id
get_quote

Returns one of your quotes. Poll it after create_quote until status is ready or failed; every few seconds is enough. Integrators only; designers are refused with actor_not_allowed.

Path parameters

  • idstringRequired

    Unique identifier of the quote, prefixed with qte_. Treat it as an opaque string: store it and compare it, never parse it.

Returns200 OK

The quote. Returns the quote object.

Responses

  • 200

    The quote.

  • 401

    Credentials are missing (missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials).

  • 403

    The credentials are valid but not allowed to do this: a scope is missing (missing_scope), the endpoint is for another kind of account (actor_not_allowed) or another kind of credential (credential_not_allowed), the account may no longer use the API (account_blacklisted), or the account must change something first, in which case details.fix_url links to the dashboard page that fixes it.

  • 404

    You have no quote with this id (quote_not_found).

  • 429

    Too many requests (rate_limited): the limit is 500 per minute per API key (or signed-in user). Wait for the number of seconds in the Retry-After header, then retry; details has limit, window_seconds, reset_at and retry_after_seconds.

Errors use the error object.

GET/v2/quotes/{id}
curl "https://public-api.dapi.digital/v2/quotes/qte_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu" \
  -H "x-api-key: $DAPI_API_KEY"
Response
{
  "id": "qte_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
  "object": "quote",
  "name": "Phone stand v2",
  "file": {
    "name": "phone-stand-v2.3mf",
    "size_bytes": 2758723,
    "download_url": "https://files.example.com/public-api/quotes/7f3a/input/phone-stand-v2.3mf?signature=abc",
    "production_version": {
      "name": "phone-stand-v2.3mf",
      "format": "3mf",
      "size_bytes": 2913004,
      "download_url": "https://files.example.com/public-api/quotes/7f3a/production/phone-stand-v2.3mf?signature=def",
      "prepared_at": "2026-10-20T09:12:09Z"
    }
  },
  "status": "ready",
  "suggested_materials": [
    {
      "slot": 1,
      "file_color": "#C12E1F",
      "file_filament_type": "PLA",
      "material": {
        "id": "mat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
        "object": "material",
        "name": "PLA Red",
        "custom": false
      },
      "match": "exact"
    },
    {
      "slot": 3,
      "file_color": "#0B2A88",
      "file_filament_type": null,
      "material": {
        "id": "mat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
        "object": "material",
        "name": "PLA Blue",
        "custom": false
      },
      "match": "close"
    }
  ],
  "price": {
    "amount": 1245,
    "currency": "usd"
  },
  "failure_reason": null,
  "approval": {
    "status": "not_submitted",
    "reason": null
  },
  "created_at": "2026-10-20T09:12:00Z",
  "finished_at": "2026-10-20T09:13:41Z"
}