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
libraryIdas a direct parameterOthers expected it within an
inputobjectSome used
library(slug) while others usedlibraryId(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?
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
Consistency: Every operation uses the same context mechanism
Cleaner Queries: No redundant library/organization IDs in every request
Fine-grained Permissions: New RBAC system enables granular access control
Better Security: Permission checks on every request
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)
x-organization (Required)Identifies the organization context. Accepts either:
Organization UUID:
550e8400-e29b-41d4-a716-446655440000Organization slug:
@my-company
x-library (Required for library-scoped operations)
x-library (Required for library-scoped operations)Identifies the library context. Accepts either:
Library UUID:
660e8400-e29b-41d4-a716-446655440000Library slug path:
@my-company/product-library
x-api-key (For API authentication)
x-api-key (For API authentication)Your API key for authentication (unchanged from v1).
Important: Your API key is scoped to a specific library. The x-library header must match the library your API key was created for. Mismatched headers will result in 403 Forbidden errors.
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.
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.
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.
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.
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
CategoryQueryNamespacefindAll
findAll(libraryId: ID!, filter: CategoryFilterInput)
findAll(filter: CategoryFilterInput)
ChangeOrdersQueryOperations
ChangeOrdersQueryOperationsget
get(library: String, filter: ChangeOrderFilterInput, pagination: PaginationInput)
get(filter: ChangeOrderFilterInput, pagination: PaginationInput)
getTemplates
getTemplates(library: String)
getTemplates
ComponentQueryNamespace
ComponentQueryNamespacefindOne
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
IdentifierQueryNamespacevalidateOverrides
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
OrganizationQueryNamespaceinvitations
invitations(filter: InvitationFilterInput): [OrganizationInvitation!]!
invitations(filter: InvitationFilterInput): [Invitation!]!
discoverByDomain
(not present)
discoverByDomain: Organization
WebhookQueryNamespace
WebhookQueryNamespacefindAll
findAll(input: FindWebhooksInput!)
findAll
6. Namespace Mutation Method Changes
Changes to methods within mutation namespaces.
ChangeOrdersMutationOperations
ChangeOrdersMutationOperationscreate
create(input: CreateChangeOrderInput!, libraryId: ID)
create(input: CreateChangeOrderInput!)
createTemplate
createTemplate(input: CreateTemplateInput!, library: String)
createTemplate(input: CreateTemplateInput!)
ConfigMutationNamespace
ConfigMutationNamespacemanuallyProcessCategoriesConfig
manuallyProcessCategoriesConfig(libraryId: String!)
manuallyProcessCategoriesConfig
OrganizationMutationNamespace
OrganizationMutationNamespacemembership
membership(organizationId: String!): MembershipMutationNamespace!
membership: MembershipMutationNamespace!
declineInvitation
(not present)
declineInvitation(id: String!): Boolean!
MembershipMutationNamespace
MembershipMutationNamespaceupdate
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
OrganizationRoleEnumSITE_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
OrganizationInvitation
Invitation
Enhanced with RBAC fields
Modified Types
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)
AltiumHealthCheckResponse
Altium integration
ViewerUrlResponse
Altium integration
GenerateViewerUrlInput
Altium integration
OrganizationInvitation
Renamed to Invitation
FindWebhooksInput
Webhooks (no longer needed)
10. New Types (Complete List)
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
Permissions: Granular capabilities like
components.create,change_orders.approveRoles: Collections of permissions (e.g., Editor, Viewer, Admin)
Role Types: Organization-level (
ORG) or Library-level (LIBRARY)Hierarchical Resolution: Library roles override organization roles for specific libraries
Role Hierarchy
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:
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
New RBAC Queries
Permission Categories
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
Remove
libraryIdparameters from all input objectsRemove
libraryandlibraryIdarguments from query/mutation callsEnsure headers are set before making requests
Step 4: Handle New Error Responses
Update error handling to recognize permission errors:
Step 5: Test Thoroughly
Test all CRUD operations for components
Test change order workflows
Test configuration updates
Verify webhook functionality
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:
Check the Error Handling guide
Review the GraphQL Playground at
https://api.durohub.com/graphqlContact 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?