Integrator onboarding

View as Markdown

Signing up as an integrator and getting the account approved.

The approval request object

A set of your quotes sent to 3DAPI to approve your integrator account. 3DAPI approves or rejects each file separately; the account is approved once 10 files are approved.

Attributes

  • idstring

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

  • objectstring

    Names the type of this object. Always approval_request.

  • statusApprovalRequestStatus
    • in_review: 3DAPI is reviewing the files. You cannot upload or send another request until it is reviewed.
    • reviewed: every file has a decision. If all were approved and you reached the required number, your account is approved; otherwise replace the rejected files and send a new request.
    Possible valuesin_reviewreviewed
  • quotesarray of object

    The quotes submitted in this request, with the decision on each file.

  • submitted_attimestamp

    Point in time, ISO 8601 in UTC.

  • reviewed_attimestamp or null

    When the review was completed. Null while in_review.

The approval request object
{
  ,
  ,
  ,
  ,
  ,
  
}

Sign up as an integrator

POST/v2/integrator/accounts

Public: no API key needed.

Credentials
None: the endpoint is public.
For
Integrators
Operation id
create_integrator_account

Creates an integrator account: a company building on the 3DAPI API. No credentials are needed and none are returned.

We email a confirmation link to the address. Open it to confirm the email (it leads to the API dashboard); only then can you sign in with the email and password and use the session or an API key for every other call. The link expires; ask for a new one with resend_integrator_confirmation.

An integrator account can never also be a seller account on 3DAPI, and a seller account cannot be converted: use an email address that has no seller account.

Limited to 10 sign-ups per IP address per hour (rate_limited, 429).

Request body

  • emailstringRequired

    Email address to sign in with. 3DAPI sends account and approval emails here.

  • passwordstringRequired

    Password to sign in with, 8 to 72 characters.

  • company_namestringRequired

    Name of the company building the integration.

Returns201 Created

The account was created and the confirmation email sent. email_confirmed is false.

Responses

  • 201

    The account was created and the confirmation email sent. email_confirmed is false.

  • 400

    The request is invalid (validation_failed), or the password is too weak for the sign-in service (weak_password).

  • 409

    An account with this email already exists (email_taken). Sign in instead, or use another email.

  • 429

    Too many requests (rate_limited): the limit is 10 per hour per IP address. Wait for the number of seconds in the Retry-After header, then retry; details has limit, window_seconds, reset_at and retry_after_seconds.

  • 503

    Sign-up is not available right now, or could not be finished (signup_unavailable). Nothing is kept in either case, so the same email can be used again. Try again later or contact support@dapi.digital.

Errors use the error object.

POST/v2/integrator/accounts
curl -X POST "https://public-api.dapi.digital/v2/integrator/accounts" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "dev@acme.example",
  "password": "correct-horse-battery",
  "company_name": "Acme Prints"
}'
Response
{
  "id": "itg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
  "object": "integrator_account",
  "email": "dev@acme.example",
  "company_name": "Acme Prints",
  "email_confirmed": false,
  "created_at": "2026-10-20T09:00:00Z"
}

Resend the confirmation email

POST/v2/integrator/accounts/confirmation

Public: no API key needed.

Credentials
None: the endpoint is public.
For
Integrators
Operation id
resend_integrator_confirmation

Sends a new confirmation link to an integrator account whose email is not confirmed yet, for example when the first link expired or never arrived. No credentials are needed.

The answer is always 202, whether or not such an account exists or is already confirmed, so this operation never reveals which emails have accounts. Nothing is sent when there is no unconfirmed integrator account for the address.

Limited to 5 requests per IP address per hour (rate_limited, 429).

Request body

  • emailstringRequired

    The email address the account was created with.

Returns202 Accepted

Accepted. If an unconfirmed integrator account uses this email, a new confirmation link is on its way. No body.

Responses

  • 202

    Accepted. If an unconfirmed integrator account uses this email, a new confirmation link is on its way. No body.

  • 400

    The request is invalid (validation_failed).

  • 429

    Too many requests (rate_limited): the limit is 5 per hour per IP address. Wait for the number of seconds in the Retry-After header, then retry; details has limit, window_seconds, reset_at and retry_after_seconds.

  • 503

    Sending confirmations is not available right now (signup_unavailable). Try again later or contact support@dapi.digital.

Errors use the error object.

POST/v2/integrator/accounts/confirmation
curl -X POST "https://public-api.dapi.digital/v2/integrator/accounts/confirmation" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "dev@acme.example"
}'
Response
null

Get your onboarding status

GET/v2/integrator/onboarding

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_integrator_onboarding

Returns where your integrator account stands: approved files so far, your upload allowance, how many quotes the next approval request needs and the latest request with its per-file decisions. Use it to decide the next step: upload more files, send a request, wait for the review or replace rejected files. Integrators only; designers are refused with actor_not_allowed.

Returns200 OK

Your onboarding status.

Responses

  • 200

    Your onboarding status.

  • 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/integrator/onboarding
curl "https://public-api.dapi.digital/v2/integrator/onboarding" \
  -H "x-api-key: $DAPI_API_KEY"
Response
{
  "object": "integrator_onboarding",
  "status": "changes_requested",
  "approved_files": 9,
  "required_files": 10,
  "uploads": {
    "used": 0,
    "limit": 25
  },
  "files_to_submit": 1,
  "current_request": {
    "id": "apr_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
    "object": "approval_request",
    "status": "reviewed",
    "quotes": [
      {
        "quote": {
          "id": "qte_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
          "object": "quote",
          "name": "Phone stand v2"
        },
        "decision": "rejected",
        "reason": "The model has open edges; close the mesh and upload it again."
      }
    ],
    "submitted_at": "2026-10-20T10:00:00Z",
    "reviewed_at": "2026-10-21T08:30:00Z"
  },
  "order_blockers": [
    "billing_details_missing"
  ]
}

List approval requests

GET/v2/integrator/approval-requests

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_approval_requests

Lists your approval requests, newest first, with the decision on each file. Integrators only; designers are refused with actor_not_allowed.

Query parameters

  • statusarray of ApprovalRequestStatus

    Only requests in these states.

    Possible valuesin_reviewreviewed
  • 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 approval requests.

Responses

  • 200

    A page of approval requests.

  • 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/integrator/approval-requests
curl "https://public-api.dapi.digital/v2/integrator/approval-requests" \
  -H "x-api-key: $DAPI_API_KEY"
Response
{
  "object": "list",
  "data": [
    {
      "id": "apr_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
      "object": "approval_request",
      "status": "reviewed",
      "quotes": [
        {
          "quote": {
            "id": "qte_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
            "object": "quote",
            "name": "Phone stand v2"
          },
          "decision": "rejected",
          "reason": "The model has open edges; close the mesh and upload it again."
        }
      ],
      "submitted_at": "2026-10-20T10:00:00Z",
      "reviewed_at": "2026-10-21T08:30:00Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Submit sample files for review

POST/v2/integrator/approval-requests

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_approval_request

Sends ready quotes to 3DAPI as sample files for review: 3DAPI checks that the files print well, which is about your files, not about access for an app or agent. Your account is approved once 10 files are approved. What a file needs: https://public-api.dapi.digital/docs/guides/file-requirements.

Send quotes to choose the files, exactly files_to_submit of them (see get_integrator_onboarding), each ready and never submitted. Omit quotes to submit your latest eligible quotes automatically.

The first request needs 10 quotes. Approved files stay approved, so after a review with rejections the next request needs only as many new quotes as were rejected. Rejected quotes cannot be submitted again: upload corrected files first.

While the request is in review you cannot create quotes or send another request. The review usually takes 24 to 48 hours; you get an email when the review is done.

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

  • quotesarray of string

    The quotes to submit, exactly files_to_submit of them, each ready and not_submitted. Omit it to submit your latest eligible quotes automatically.

Returns201 Created

The request, in review. Returns the approval request object.

Responses

  • 201

    The request, in review.

  • 400

    The request is invalid (validation_failed), for example quotes does not hold exactly files_to_submit ids.

  • 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 is already approved (already_approved), or a request is already in review (approval_in_review).

  • 422

    Without quotes, you have fewer eligible quotes than files_to_submit (not_enough_ready_quotes, details.required and details.available). With quotes, one of them is unknown, listed twice, still being priced, failed, already submitted, approved or rejected (quote_not_eligible, details.quote and details.reason: not_found, duplicate, not_ready, failed, in_review, approved or rejected).

  • 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.

POST/v2/integrator/approval-requests
curl -X POST "https://public-api.dapi.digital/v2/integrator/approval-requests" \
  -H "x-api-key: $DAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
Response
{
  "id": "apr_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
  "object": "approval_request",
  "status": "in_review",
  "quotes": [
    {
      "quote": {
        "id": "qte_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
        "object": "quote",
        "name": "Phone stand v2"
      },
      "decision": "pending",
      "reason": null
    }
  ],
  "submitted_at": "2026-10-20T10:00:00Z",
  "reviewed_at": null
}

Get an approval request

GET/v2/integrator/approval-requests/{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_approval_request

Returns one of your approval requests with the decision and reason for each file. Integrators only; designers are refused with actor_not_allowed.

Path parameters

  • idstringRequired

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

Returns200 OK

The approval request. Returns the approval request object.

Responses

  • 200

    The approval request.

  • 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 approval request with this id (approval_request_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/integrator/approval-requests/{id}
curl "https://public-api.dapi.digital/v2/integrator/approval-requests/apr_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu" \
  -H "x-api-key: $DAPI_API_KEY"
Response
{
  "id": "apr_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
  "object": "approval_request",
  "status": "reviewed",
  "quotes": [
    {
      "quote": {
        "id": "qte_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
        "object": "quote",
        "name": "Phone stand v2"
      },
      "decision": "rejected",
      "reason": "The model has open edges; close the mesh and upload it again."
    }
  ],
  "submitted_at": "2026-10-20T10:00:00Z",
  "reviewed_at": "2026-10-21T08:30:00Z"
}