Skip to main content
Product lifecycle management (PLM) API for hardware teams — query and manage components, BOM assemblies, libraries, and engineering change orders through a single GraphQL endpoint. Best for agents that read part data and revisions, create or update components, or drive change-management workflows (open change orders, add affected items). Unlike heavyweight PLMs like Arena or Windchill, Duro is an out-of-the-box, API-first PLM; every request is a POST to https://api.durohub.com/graphql with the operation in the body — see the routing hint for header and operation shapes. 9 example endpoints available through Lava’s AI Gateway. See the Duro API docs for full documentation.
This provider requires your own credentials — connect your API key or OAuth account before use.
This is a catch-all provider — any valid URL under https://api.durohub.com/graphql is supported. Duro PLM GraphQL API. Single endpoint: POST https://api.durohub.com/graphql. Auth is supplied automatically from the connected credential (x-api-key + x-organization + x-library; a key is scoped to one org/library). Each request POSTs a JSON body with a “query” string (the GraphQL document) and an optional “variables” object. Resources are namespaced: component.findOne(id), component.findAll(filter, pagination), component.create(inputs), component.update(inputs), component.delete(ids); changeOrders.get(filter, pagination), changeOrders.create(input), changeOrders.addItems(changeOrderId, input), changeOrders.submitForReview(id); plus libraries. Pagination is Relay cursor: pass pagination with first:N and after:cursor, then read the edges/node list alongside pageInfo (hasNextPage, endCursor) and totalCount (changeOrders nests these under a connection field). Filtering: component.findAll accepts a filter with categoryType (PART, ASSEMBLY, or DOCUMENT), name, cpns, statusId, and isArchived. Updates support optimistic concurrency via expectedVersion. Errors: GraphQL always returns HTTP 200 — failures appear in the top-level errors array with extensions.code (FORBIDDEN, or RATE_LIMITED with extensions.retryAfter seconds). Component delete is permanent; prefer update with isArchived:true to archive. See https://docs.durohub.com/ for the full reference. The endpoints below are curated examples.

Endpoints

List the libraries available to the connected key. Use as an auth/connectivity check (the “hello world” query) and to confirm the library slug.

POST https://api.durohub.com/graphql — Free
const data = await lava.gateway('https://api.durohub.com/graphql', { body: {"query":"query Libraries { libraries { id name slug } }"} });

List components with optional filtering and Relay cursor pagination. Filter by categoryType (PART, ASSEMBLY, DOCUMENT), name, cpns, status, or archived flag.

POST https://api.durohub.com/graphql — Free
const data = await lava.gateway('https://api.durohub.com/graphql', {
  body: {
"query": "query ListComponents { component { findAll(filter: { categoryType: PART, isArchived: false }, pagination: { first: 20 }) { edges { node { id name revisionValue version status { name } category { name } } } pageInfo { hasNextPage endCursor } } } }"
},
});

Fetch a single component by its UUID, including revision, status, category, and timestamps.

POST https://api.durohub.com/graphql — Free
const data = await lava.gateway('https://api.durohub.com/graphql', {
  body: {
"query": "query GetComponent { component { findOne(id: \"550e8400-e29b-41d4-a716-446655440000\") { id name description revisionValue version state status { name color } category { name type } createdAt updatedAt } } }"
},
});

Create one or more components. name is required; categoryId, description, revisionValue, eid, and attributeValues are optional. Returns the created components with their assigned revisionValue and version.

POST https://api.durohub.com/graphql — Free
const data = await lava.gateway('https://api.durohub.com/graphql', {
  body: {
"query": "mutation CreateComponent($inputs: [CreateComponentInput!]!) { component { create(inputs: $inputs) { id name revisionValue version createdAt } } }",
"variables": {
  "inputs": [
    {
      "name": "Capacitor 100uF",
      "description": "Electrolytic capacitor, 100uF 25V",
      "categoryId": "part-category-uuid"
    }
  ]
}
},
});

Update one or more components by ID. Pass expectedVersion for optimistic concurrency (the update fails with a conflict if the current version differs). Set isArchived: true to archive rather than delete.

POST https://api.durohub.com/graphql — Free
const data = await lava.gateway('https://api.durohub.com/graphql', {
  body: {
"query": "mutation UpdateComponent($inputs: [UpdateComponentInput!]!) { component { update(inputs: $inputs) { id name description version updatedAt } } }",
"variables": {
  "inputs": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "name": "Motor Assembly v2",
      "expectedVersion": 1
    }
  ]
}
},
});

Permanently delete components by their IDs. This is irreversible — prefer archiving via update (isArchived: true) when you may need the component later.

POST https://api.durohub.com/graphql — Free
const data = await lava.gateway('https://api.durohub.com/graphql', {
  body: {
"query": "mutation DeleteComponents { component { delete(ids: [\"123e4567-e89b-12d3-a456-426614174000\"]) } }"
},
});

List change orders with optional filtering (by status, resolution, assignee, or stage) and cursor pagination. Results are wrapped in a connection { edges { node } } envelope.

POST https://api.durohub.com/graphql — Free
const data = await lava.gateway('https://api.durohub.com/graphql', {
  body: {
"query": "query GetChangeOrders { changeOrders { get(filter: { status: [DRAFT, OPEN] }, pagination: { first: 20 }) { connection { edges { node { id sequentialId name status resolution createdAt createdBy { firstName lastName email } } } pageInfo { hasNextPage endCursor } } totalCount } } }"
},
});

Create a change order in DRAFT status. Returns its sequentialId plus the configured approval stages and content fields. Add affected components next with addItems.

POST https://api.durohub.com/graphql — Free
const data = await lava.gateway('https://api.durohub.com/graphql', {
  body: {
"query": "mutation CreateChangeOrder { changeOrders { create(input: { name: \"ECO-2024-001: Update Motor Specifications\", description: \"Updating motor torque specifications to meet new performance requirements\" }) { id sequentialId name status resolution stages { id name order decisionMethod } createdAt } } }"
},
});

Add components (the affected items) to a change order, each pinned to a component version. Use updateProposalsForItems afterward to set the proposed revision/status.

POST https://api.durohub.com/graphql — Free
const data = await lava.gateway('https://api.durohub.com/graphql', {
  body: {
"query": "mutation AddItems { changeOrders { addItems(changeOrderId: \"123e4567-e89b-12d3-a456-426614174000\", input: { items: [{ id: \"component-uuid-1\", version: 3 }] }) { id itemId itemVersion proposedRevision proposedStatusId } } }"
},
});

Next Steps

All Providers

Browse all supported AI providers

Forward Proxy

Learn how to construct proxy URLs and authenticate requests