API v2 Migration Guide

This guide provides comprehensive information for migrating your existing Duro API integrations to API v2. This is a breaking change release that introduces a new header-based context system and role-based access control (RBAC).

Overview

Why This Change?

The previous API suffered from inconsistent context handling:

  • Some operations required libraryId as a direct parameter

  • Others expected it within an input object

  • Some used library (slug) while others used libraryId (UUID)

  • Organization context was sometimes explicit, sometimes implicit

API v2 standardizes context through HTTP headers, eliminating redundancy and providing a cleaner, more predictable interface.

What's New?

Feature
v1 (Legacy)
v2 (New)

Library Context

Parameter in each operation

x-library header

Organization Context

Parameter in some operations

x-organization header

Access Control

Simple role enum

Full RBAC with permissions

API Key Scope

Tied to library at creation

Must match x-library header

Key Benefits

  1. Consistency: Every operation uses the same context mechanism

  2. Cleaner Queries: No redundant library/organization IDs in every request

  3. Fine-grained Permissions: New RBAC system enables granular access control

  4. Better Security: Permission checks on every request

  5. Simplified Client Code: Set headers once, use everywhere


Migration Checklist

Before starting your migration:


Required Headers

All authenticated API requests must include these headers:

x-organization (Required)

Identifies the organization context. Accepts either:

  • Organization UUID: 550e8400-e29b-41d4-a716-446655440000

  • Organization slug: @my-company

x-library (Required for library-scoped operations)

Identifies the library context. Accepts either:

  • Library UUID: 660e8400-e29b-41d4-a716-446655440000

  • Library slug path: @my-company/product-library

x-api-key (For API authentication)

Your API key for authentication (unchanged from v1).

Complete Request Example


Complete Breaking Changes Reference

This section provides exhaustive tables of every change grouped by category.


1. Input Objects: Removed Fields

Fields removed from input types - context now provided via headers.

Input Type
Removed Field(s)
Header to Use

BulkCreateReusableInstancesInput

libraryId: String!

x-library

CategoryFilterInput

libraryId: String

x-library

ComponentFilterInput

libraryId: String, libraryIds: [String!]

x-library

ConfigFilterInput

libraryId: String

x-library

ConfigureLibraryInput

libraryId: String!

x-library

CreateApiKeyInput

libraryId: String!

x-library

CreateComponentInput

libraryId: ID!

x-library

CreateLibraryInput

organizationId: String!

x-organization

CreateValidationRuleInput

libraryId: ID!

x-library

CreateWebhookInput

libraryId: String!

x-library

CustomStatusFilterInput

libraryId: String

x-library

DeactivateApiKeyInput

libraryId: String!

x-library

FindAllApiKeyForUserInput

libraryId: String

x-library

FindOneApiKeyForUserInput

libraryId: String

x-library

IdsFilterInput

libraryId: String

x-library

IsPinnedComponentInput

libraryId: ID!

x-library

NextRevisionInput

libraryId: String!

x-library

PinComponentsInput

libraryId: ID!

x-library

RevokeAllApiKeysForUserInput

libraryId: String!

x-library

RotateApiKeyInput

libraryId: String!

x-library

SetLibraryConfigInput

libraryId: String!

x-library

UnPinComponentsInput

libraryId: ID!

x-library

UpdateApiKeyInput

libraryId: String!

x-library

UpdateComponentInput

libraryId: ID

x-library

ValidateApiKeyInput

libraryId: String!

x-library

ValidateRevisionValueInput

libraryId: String!

x-library

ValidationRuleFilter

libraryId: ID

x-library

NaturalLanguageSearchInput

libraryIds: [String!]

x-library


2. Input Objects: Modified Fields

Fields changed or deprecated in input types.

Input Type
Field
v1 (Legacy)
v2 (New)

BulkInviteInput

role

role: OrganizationRoleEnum! (required)

role: OrganizationRoleEnum (optional, deprecated)

BulkInviteInput

roleId

(not present)

roleId: String (deprecated, use orgRoleId)

BulkInviteInput

orgRoleId

(not present)

orgRoleId: String (new, preferred)

BulkInviteInput

libraryRoles

(not present)

libraryRoles: [LibraryRoleAssignment!] (new)


3. Root Query Changes

Changes to top-level Query fields.

Query
v1 Signature
v2 Signature
Change Type

altiumHealthCheck

altiumHealthCheck: AltiumHealthCheckResponse!

(removed)

REMOVED

customStatuses

customStatuses(filter: CustomStatusFilterInput!)

customStatuses(filter: CustomStatusFilterInput)

Filter now optional

configs

configs(filter: ConfigFilterInput!)

configs(filter: ConfigFilterInput)

Filter now optional

configSyncStatus

configSyncStatus(libraryId: String!, type: ConfigType!)

configSyncStatus(type: ConfigType!)

libraryId removed

libraries

libraries(organizationId: ID!)

libraries

organizationId removed

roles

(not present)

roles: RoleQueryNamespace!

NEW


4. Root Mutation Changes

Changes to top-level Mutation fields.

Mutation
v1 Signature
v2 Signature
Change Type

generateAltiumViewerUrl

generateAltiumViewerUrl(input: GenerateViewerUrlInput!)

(removed)

REMOVED

membership

membership: MembershipMutationNamespace!

(removed from root)

Moved to organization.membership

roles

(not present)

roles: RoleMutationNamespace!

NEW


5. Namespace Query Method Changes

Changes to methods within query namespaces.

CategoryQueryNamespace

Method
v1 Signature
v2 Signature

findAll

findAll(libraryId: ID!, filter: CategoryFilterInput)

findAll(filter: CategoryFilterInput)

ChangeOrdersQueryOperations

Method
v1 Signature
v2 Signature

get

get(library: String, filter: ChangeOrderFilterInput, pagination: PaginationInput)

get(filter: ChangeOrderFilterInput, pagination: PaginationInput)

getTemplates

getTemplates(library: String)

getTemplates

ComponentQueryNamespace

Method
v1 Signature
v2 Signature

findOne

findOne(id: ID!): Component!

findOne(id: ID!): Component (now nullable)

validateAttributes

validateAttributes(categoryId: ID!, attributeValues: [AttributeValueInput!]!, libraryId: ID!)

validateAttributes(categoryId: ID!, attributeValues: [AttributeValueInput!]!)

getAllPinnedComponents

getAllPinnedComponents(libraryId: String!)

getAllPinnedComponents

IdentifierQueryNamespace

Method
v1 Signature
v2 Signature

validateOverrides

validateOverrides(libraryId: String!, overrides: [IdElementOverrideInput!]!)

validateOverrides(overrides: [IdElementOverrideInput!]!)

validateCompleteOverride

validateCompleteOverride(libraryId: String!, overrides: [IdElementOverrideInput!]!, componentId: String)

validateCompleteOverride(overrides: [IdElementOverrideInput!]!, componentId: String)

overridePermissions

overridePermissions(libraryId: String!)

overridePermissions

reusableGroupInstances

reusableGroupInstances(libraryId: String!, configId: String!, groupName: String!, filters: [ElementValueInput!])

reusableGroupInstances(configId: String!, groupName: String!, filters: [ElementValueInput!])

validateFreeformOverride

validateFreeformOverride(libraryId: String!, value: String!, componentId: String)

validateFreeformOverride(value: String!, componentId: String)

OrganizationQueryNamespace

Method
v1 Signature
v2 Signature

invitations

invitations(filter: InvitationFilterInput): [OrganizationInvitation!]!

invitations(filter: InvitationFilterInput): [Invitation!]!

discoverByDomain

(not present)

discoverByDomain: Organization

WebhookQueryNamespace

Method
v1 Signature
v2 Signature

findAll

findAll(input: FindWebhooksInput!)

findAll


6. Namespace Mutation Method Changes

Changes to methods within mutation namespaces.

ChangeOrdersMutationOperations

Method
v1 Signature
v2 Signature

create

create(input: CreateChangeOrderInput!, libraryId: ID)

create(input: CreateChangeOrderInput!)

createTemplate

createTemplate(input: CreateTemplateInput!, library: String)

createTemplate(input: CreateTemplateInput!)

ConfigMutationNamespace

Method
v1 Signature
v2 Signature

manuallyProcessCategoriesConfig

manuallyProcessCategoriesConfig(libraryId: String!)

manuallyProcessCategoriesConfig

OrganizationMutationNamespace

Method
v1 Signature
v2 Signature

membership

membership(organizationId: String!): MembershipMutationNamespace!

membership: MembershipMutationNamespace!

declineInvitation

(not present)

declineInvitation(id: String!): Boolean!

MembershipMutationNamespace

Method
v1 Signature
v2 Signature

update

update(userId: String!, role: OrganizationRoleEnum!)

update(userId: String!, roleId: String!)

updateLibraryAccess

(not present)

updateLibraryAccess(input: UpdateLibraryAccessInput!): Boolean!

removeOrgRole

(not present)

removeOrgRole(userId: String!): Boolean!


7. Enum Changes

OrganizationRoleEnum

v1 Values
v2 Values
Notes

SITE_ADMIN

SITE_ADMIN

Unchanged

ADMIN

ADMIN

Unchanged

USER

EDITOR

RENAMED

APPROVER

(removed)

REMOVED - use EDITOR

REVIEWER

REVIEWER

Unchanged

(not present)

VIEWER

NEW

SUPPLIER

SUPPLIER

Unchanged


8. Type Changes

Renamed Types

v1 Type
v2 Type
Notes

OrganizationInvitation

Invitation

Enhanced with RBAC fields

Modified Types

Type
Change

Organization

Added roles: [Role!]! field

Organization

Changed invitations return type to [Invitation!]!

OrganizationRole

Added rbacRole: Role, hasDirectOrgRole: Boolean!, libraryAccess: [LibraryAccessDto!]

Library

Added stats: LibraryStatsType field


9. Removed Types (Complete List)

Removed Type
Category

AltiumHealthCheckResponse

Altium integration

ViewerUrlResponse

Altium integration

GenerateViewerUrlInput

Altium integration

OrganizationInvitation

Renamed to Invitation

FindWebhooksInput

Webhooks (no longer needed)


10. New Types (Complete List)

New Type
Category
Purpose

Role

RBAC

Defines a role with permissions

Permission

RBAC

Individual permission definition

RoleType

RBAC

Enum: ORG, LIBRARY

RoleMutationNamespace

RBAC

Mutations for role management

RoleQueryNamespace

RBAC

Queries for role management

CreateRoleInput

RBAC

Input for creating custom roles

UpdateRoleInput

RBAC

Input for updating roles

DeleteRoleInput

RBAC

Input for deleting roles

Invitation

Invitations

Replaces OrganizationInvitation

LibraryAccessDto

RBAC

Library-specific role info

LibraryRoleAssignment

RBAC

Input for assigning library roles

LibraryStatsType

Library

Component/user counts

UpdateLibraryAccessInput

RBAC

Input for updating user library access


11. Code Examples (Before/After)

Quick reference examples for common operations.

Components

Change Orders

Libraries

Membership


Role-Based Access Control (RBAC)

API v2 introduces a comprehensive RBAC system that replaces the simple role enum approach.

Key Concepts

  1. Permissions: Granular capabilities like components.create, change_orders.approve

  2. Roles: Collections of permissions (e.g., Editor, Viewer, Admin)

  3. Role Types: Organization-level (ORG) or Library-level (LIBRARY)

  4. Hierarchical Resolution: Library roles override organization roles for specific libraries

Role Hierarchy

Level
Description

Organization Role

Default permissions for all libraries in the org

Library Role

Override permissions for a specific library

Example: A user with Org Editor role but Library Viewer role for "Engineering Library" will have:

  • Editor permissions in all other libraries

  • Viewer (read-only) permissions in Engineering Library

Legacy Role Mapping

If you were using the legacy OrganizationRoleEnum, here's how roles map:

Legacy Enum
New System Role
Permissions

SITE_ADMIN

Site Admin

Full system access (admin)

ADMIN

Admin

Full organization access (admin)

USER

Editor

Create, edit, approve change orders

APPROVER

Removed

Use Editor or Reviewer

REVIEWER

Viewer

Read-only access

SUPPLIER

Supplier

Limited external access

The USER role has been renamed to EDITOR to better reflect its capabilities. The APPROVER role has been removed - use EDITOR for users who need to approve change orders.

New RBAC Queries

Permission Categories

Resource
Actions

components

create, read, update, delete, revision.create

assemblies

create, read, update, delete

change_orders

create, read, update, delete, submit, approve, reject, release, withdraw, reset

library

read, settings.update, categories.manage, statuses.manage, features.manage

organization

read, settings.update, users.read, users.invite, users.remove, users.update_role

roles

read, create, update, delete, assign

comments

create, read, update, delete, moderate

Permission Errors

API v2 will return 403 Forbidden with detailed error codes when permission checks fail:


Invitation System Changes

Type Rename

The OrganizationInvitation type has been renamed to Invitation and enhanced with RBAC support:

Bulk Invite Changes


Efficient Migration Strategy

Step 1: Update HTTP Client Configuration

Configure your HTTP client to automatically include context headers:

Step 2: Search and Replace Input Objects

Use these regex patterns to find affected code:

Step 3: Update Query/Mutation Calls

  1. Remove libraryId parameters from all input objects

  2. Remove library and libraryId arguments from query/mutation calls

  3. Ensure headers are set before making requests

Step 4: Handle New Error Responses

Update error handling to recognize permission errors:

Step 5: Test Thoroughly

  1. Test all CRUD operations for components

  2. Test change order workflows

  3. Test configuration updates

  4. Verify webhook functionality

  5. Test with different user roles


FAQ

Q: Can I use both v1 and v2 patterns?

A: No. The v2 schema removes the parameters entirely. You must update all calls.

Q: What if I access multiple libraries?

A: Change the x-library header for each request. Most HTTP clients support per-request header overrides.

Q: How do I get my organization/library slugs?

A: View your URL in Duro: durohub.com/org/@org-slug/libs/library-slug. The slugs are the @org-slug and library-slug portions.

Q: My API key was created for a specific library. Do I need a new one?

A: No, existing API keys continue to work. Just ensure your x-library header matches the library your key was created for.

Q: What happens if headers are missing?

A: You'll receive a 400 Bad Request error indicating which headers are required.


Support

If you encounter issues during migration:

  1. Check the Error Handling guide

  2. Review the GraphQL Playground at https://api.durohub.com/graphql

  3. Contact support at [email protected]


Next Steps

  • Explore the GraphQL Playground with the new schema

  • Update your Webhooks configuration if needed

  • Review the complete permission list in your organization's Settings > Roles & Permissions

Last updated

Was this helpful?