At Sage Active, we strive to maintain backward compatibility to ensure a seamless experience for our users.
Most changes to our API are designed to be non-disruptive and are implemented in a way that preserves existing functionality.
However, there are exceptions where, in the best interest of the product and its users, breaking compatibility is necessary.
In such cases, maintaining an element that could negatively impact performance, security, or usability would be detrimental to the overall user experience and the product’s evolution.
Therefore, when a breaking change is unavoidable, it is made with careful consideration of its necessity and potential benefits, aiming to minimize disruption and provide clear migration paths for all affected users.
Here is a list of recent breaking changes that you may need to adapt to:
All Resources
2025 September
Change: The cost directive has undergone structural changes during the migration from HotChocolate v13 to v15:
The argument weight was added
The arguments complexity, defaultMultiplier, multipliers and MultiplierPath were removed
Reason: In HotChocolate v15, the internal cost analysis system was redesigned to simplify and standardize performance cost estimation across resolvers.
The former approach using complexity, defaultMultiplier, multipliers and MultiplierPath has been deprecated in favor of a single weight argument that is easier to configure and interpret. This is part of a broader refactoring of the execution engine in HotChocolate to make middleware resolution and cost-based batching more predictable and performant.
Impact:
Any custom usage or tooling that relied on the previous cost directive arguments will break unless updated.
If you used @cost(complexity: X) or similar in your schema extensions or stitching logic, you must now use@cost(weight: X) instead.
Existing introspection queries or documentation tools expecting the old arguments will no longer find them.
This change reflects a breaking change in the GraphQL schema and may cause errors at runtime if clients still attempt to use the old directive structure.
Solution:
Update all usages of the @cost directive to conform to the new syntax introduced in HotChocolate v15.
Review all schema stitching and introspection-dependent tooling to ensure compatibility with the updated directive shape.
Resource: All resources using DateOperationFilterInput
2025 September COMING SOON This feature is currently in development and will be available in the next version. It’s already documented to keep you informed about its upcoming availability
Change:
Type Date was removed
All input fields in DateOperationFilterInput changed from Date to DateTime:
eq, neq, gt, gte, lt, lte, ngt, ngte, nlt, nlte
in and nin changed from [Date] to [DateTime]
Reason:
The Date scalar type was used exclusively in filter operators. In Sage Active, business dates such as invoice dates or accounting entry dates use a date-only format, while system dates like creationDate and modificationDate use full datetime values.
In HotChocolate 13, the Date type in filters was permissive: it accepted both date-only and datetime values, even though the time part was ignored.
In HotChocolate 15, this behavior is no longer supported. For consistency and compatibility, the Date type has been removed from filters and replaced by DateTime.
Impact:
Filters that pass datetime or date-only values directly (e.g., in literals or Postman queries) will continue to work as before.
The only breaking change occurs if your GraphQL query variables were explicitly typed as Date and used to filter business dates. In this case, you must update the variable type from Date to DateTime.
The impact should be minimal or nonexistent, as production API usage statistics show no cases where variables of type Date were declared for date filters.
Recommendation:
Review your client-side code and update any GraphQL variables typed as Date to use DateTime, especially if used in filters involving business dates.
Change: The following fields were removed from the official schema:
legislationCode from DocumentType
isMainAddress from EmployeeAddress
taxOfficialModelId from TaxOfficialModelOrganization
townId from ZipCode
Reason:
legislationCode was unnecessary since document types are already filtered based on the current legislation.
isMainAddress was redundant as each employee can only have one address.
taxOfficialModelId had no corresponding resource to resolve the ID to a meaningful value.
townId had no corresponding resource to resolve the ID to a meaningful value.
Note:
These fields are no longer present in the official schema. However, they remain technically accessible for now.
It is recommended to remove them from any GraphQL queries where they are explicitly used, in preparation for their permanent deletion in a future version.
accountingEntryTemplateId from JournalTypeCreateGLDtoInput
purchaseUnitPrice from ProductCreateGLDtoInput
blockDeliveryNoteEnabled, blockInvoiceEnabled, and blockOrderEnabled from both SupplierCreateGLDtoInput and SupplierUpdateGLDtoInput
Change: Several fields in the CustomerSortInput and SupplierSortInput input types changed type:
countryAcronym from StringOperationFilterInput to SortEnumType
documentType from DocumentTypeFilterInput to DocumentTypeSortInput
documentTypeId from UuidOperationFilterInput to SortEnumType
tradeName from StringOperationFilterInput to SortEnumType
Reason:
The removed fields were part of a feature that was ultimately not implemented and never made officially available. This is a cleanup of unused elements.
The type changes reflect a cleanup and standardization effort: sort inputs should use only sort-compatible types (SortEnumType) and not filtering types.
Solution:
Ensure that no GraphQL queries rely on the removed fields. Since they were never functional, their removal has no impact on integration.
Change: The fields activeOrganizationId, activeTenantId, and activeLegislationCode now return empty values (GUID.empty for the first two, and null for the last).
Reason: These fields have not been meaningful for over a year, following a change in how organizations are authorized for a user, they can now technically belong to different tenants.
Although these fields were removed from the documentation, they remained in the API to avoid execution errors when querying userProfile.
Solution: Remove these fields from the userProfile query. They are no longer relevant and will be permanently removed in a future version.
Change: The sourceType input field for sales document filters (SalesQuoteFilterInput, SalesOrderFilterInput, SalesInvoiceFilterInput, and SalesDeliveryNoteFilterInput) no longer accepts null.
Reason: Previously, sourceType was nullable. Now, it always takes a value: SALES when the document is manually entered, and PUBLIC_API when created through the API.
Solution: Update filters to explicitly set sourceType, depending on the origin of the document.
Change: The dataloader accountingEntry and the field accountingEntryId were removed from the salesInvoices dataloader, which is accessible from accountingEntries.
Reason: While it was technically functional, exposing accountingEntries through this dataloader was redundant, as the query already originated from the accounting entry. Additionally, it introduced a circular reference issue when sales invoices contained advance payment deductions, leading to multiple accounting entries being linked to the same sales invoice.
Solution: It remains possible to access the sales invoice header from an accounting entry if it exists.
Change: The types AccountingAccountGLDto and TaxTreatmentGLDto were removed.
Reason: The list of Tax Treatments was already available through the dataloader logic, accessible from AccountingAccount. However, the list of Tax Treatments as a standalone entity remained as a DTO, as an exception to the general rule introduced with dataloaders.
Additionally, TaxTreatmentGLDto contained published fields that were not being used.
Solution: If you were using a field from TaxTreatmentGLDto that has been removed due to being unused, simply remove it from your query. No other modifications are required as the Tax Treatment list remains accessible through AccountingAccount.
Change: Fields xxxx changed type from Int to Decimal.
Reason: The January version of Sage Active introduces the ability to handle quantities with decimals in sales documents.
This results in technical breaking changes as quantities now shift from Int to Decimal. However, this does not impact existing developments because Decimal supports Int.
Solution: No modifications are required, as compatibility is maintained.
Change: The input field taxGroupId was removed from the input object type PurchaseInvoiceLineCreateGLDtoInput.
Reason: The API schema has been updated to simplify the handling of tax groups, ensuring a more streamlined and consistent data structure for purchase invoice lines.
Solution: Remove any references to the taxGroupId field in your Purchase Invoices mutations.
Change: The input field lines was removed from the input object type PurchaseInvoiceCreateGLDtoInput. The input field vatLines of type [PurchaseInvoiceLineCreateGLDtoInput!]! was added instead.
Reason: The structure of the purchase invoice creation process has been improved to better handle VAT lines separately, providing more clarity and precision in the data model.
Solution: Update your queries and mutations by replacing references to the lines input field with the new vatLines input field.
Change: The status field of organizations is no longer relevant and should not be used to check the status of organizations.
Reason: Access permission management for an organization now depends on business management, which allows, for example, the termination of a business’s use. Additionally, the status field always returns the value READY, making it meaningless for determining an organization’s status.
Solution: Either remove the status field if it was referenced in queries on organization, or, if kept, ensure that its returned value is no longer taken into account.
Change: The comments field length has been reduced from 65536 characters to 250.
Reason: This change was implemented to mitigate performance impact risks if large volumes are added.
Solution: Ensure during the creation and modification of products that the length of comment values does not exceed 250 characters. Replace overly lengthy content with a hyperlink that leads to a page displaying detailed comments.
Change: The mainAddress and deliveryAddress for salesDocuments were previously exposed as arrays. Now, they are presented in a simple format.
Reason: These objects contained only one element, and simplifying their structure facilitates filtering, such as retrieving sales quotes from clients in Brussels.
Solution: When retrieving data, remove the index [0].
For example, use salesQuoteNode.mainAddress instead of salesQuoteNode.mainAddress[0].
Change: The defaultAccountingAccountId field in Customers and Suppliers is no longer filterable or sortable.
Reason: The introduction of dataloaders has currently prevented filtering on this field, which was possible in previous versions. A solution is being studied for a future version.
Solution: Remove the filter or sort from the query and perform local filtering on the response data.
Resource: All Resources
2024 May
Change: In the syntax of queries using fragments, the DTO used to qualify fragment fields is no longer compatible due to the transition to data loaders.
Reason: This update is part of a move to simplify query writing and to enhance performance with the use of data loaders.
Solution: Replace the DTO name in the fragment syntax with the name of the resource in singular form, starting with a capital letter.
Example for a query users, fragment UserProps on UserGLDto becomes fragment UserProps on User.
Resource: Other removed fields
2024 May
Changes: All of these fields are REMOVEDThis feature has been removed and will cause a compatibility break if it was previously in use.
salesQuotes -> action
salesOrders -> action
salesDeliveryNotes -> action
salesInvoices -> action
salesTariffs -> calculationBase
suppliers / thirdCollectorName
paymentMeans -> inactive
paymentMeans -> paymentMethodId
paymentMeans -> paymentMethodReferenceName
organizations -> isDefaultDeliveryAddress
organizations -> isDeliveryAddress
organizations -> isMainAddress
zipcode -> code
Reason: These fields were historically present but became inconsistent with the developments in Sage Active. They have been removed to avoid the implication that they may contain incoherent data.
Solution: Remove these fields from queries and modify the code responsible for retrieving data from the affected queries.
Change: The activeOrganizationId field no longer returns the current user’s active organization in Sage Active, but instead returns the first organization assigned to the user.
Reason: The information returned was no longer relevant, leading to its removal from the documentation, though the field still exists to prevent query errors.
Solution: Manage the current user’s organization in a local cache to retrieve it upon the user’s next login.