Release 26.09 adds partial updates (PATCH) on matters, ordering on the user list, and a practice group filter on matters, and it tightens validation on Peppol identifiers, trust accounting bookings, and translated fields. Review the changes below to assess the impact on your integration.
Important changes
Peppol identifiers are validated when written through the API
PUT /api/v3/firms/{id}/ validates peppol_id, and POST /api/v3/contacts/ and PUT /api/v3/contacts/{id}/ validate peppol_id and peppol_company_id on debtor organizations. A value must consist of a scheme ID and an endpoint ID separated by a colon, for example 0106:12345678, and the scheme ID must be one of the registered schemes. Anything else returns HTTP 400.
Validation applies to the values a request changes: a PUT that resends the stored identifier unchanged is accepted, so an existing value never blocks an update to other fields. An identifier that does not follow this structure cannot be rendered into a UBL e-invoice, which is why the API rejects it at the point of writing.
Archive status and archive date are preserved on updates
PUT on /api/v3/matters/, /api/v3/clients/, /api/v3/contacts/, /api/v3/submatters/, and /api/v3/subscriptions/ treats archived_date as read-only. A request that includes it keeps the stored value, and the date follows the archive status. The field is still returned on GET.
A PUT that omits softkill_status leaves the object at its current status, archived objects included. Send softkill_status explicitly to archive or reactivate an object, or, preferably, use POST /api/v3/matters/{id}/archive/ and POST /api/v3/matters/{id}/unarchive/ for matters.
Note: a future release adds dedicated archive and unarchive endpoints for the other resources and deprecates archiving through softkill_status. The softkill_status path keeps working until then.
Translated fields carry a schema and stricter value validation
Fields that hold one value per language, such as external_name on /api/v3/functions/ and name_on_invoice on /api/v3/submatterkinds/, are described in the OpenAPI document as an object mapping language code to string, with an example payload and the language codes configured for the firm. The Swagger form accepts that object, so these fields can be submitted from the documentation. The object must carry an entry for every configured code; a missing or unrecognized code returns HTTP 400.
An entry whose value is not a string returns HTTP 400. An empty string is accepted where the underlying field allows a blank value, for example name and default_description on /api/v3/activities/, and rejected where it does not.
PUT /api/v3/matters/{id}/ preserves access_kind: a request that omits access_kind keeps the matter's stored access kind. Send the field explicitly to change it, including when you want the firm default. On POST, an omitted access_kind still takes the firm default.
GET /api/v3/me/ always returns avatar URLs: avatars holds an object mapping avatar size to URL for every user. A user without an uploaded picture gets a generated avatar with their initials, so the field does not return null.
Custom field values are not capped at 255 characters: entries in custom_fields accept a value of any length on every endpoint that exposes them, matching the storage behind the field.
New endpoint
Partial updates on matters
PATCH /api/v3/matters/{id}/ updates only the fields present in the request body; omitted fields keep their stored value. Matters are the only resource that accepts PATCH; every other resource continues to expose PUT with its full-replace contract, which is unchanged.
tags, users, and activity_groups are replaced wholesale when included, so send the complete list rather than a difference. custom_fields merges by identifier: an identifier you do not mention keeps its value, an entry sent with value set to an empty string clears it, null is rejected, and an empty list is a no-op.
Read-only fields are rejected with HTTP 400 instead of ignored, and fields that are read-only because of a permit or firm configuration return HTTP 403. Archive a matter through POST /api/v3/matters/{id}/archive/ and POST /api/v3/matters/{id}/unarchive/ rather than through a partial update. Coupled fields are validated against the merged result, not against the request alone. See the documentation on the endpoint in Swagger for more information.
Modified endpoints
GET /api/v3/users/ accepts an ordering parameter: the supported values are name, last_name, first_name, id, begin_date, end_date, employee_number, modified_date, and username. Prefix a value with - for descending order and separate several values with a comma, for example ?ordering=last_name,-username. ordering=name sorts by last name, name prefix, first name, username, and id, matching the user list in the interface. Without the parameter, the list is ordered by id ascending.
GET /api/v3/matters/ accepts a practice_group filter: ?practice_group=1 returns the matters in that practice group, matched on the exact practice group id. The filter is available whether or not the practice group feature is enabled for the firm, and it accepts deactivated practice groups. An unknown or non-numeric id returns HTTP 400.
PUT /api/v3/matterbudgets/{id}/ resolves budget values before validating them: the checks that require hours for an hours budget and amount for an amount budget run against the budget kind that will be stored and against the values already on the budget, so a request that omits amount or hours is accepted when the stored value satisfies the kind. On POST, an omitted kind resolves to the default before those checks run.
/api/v3/trustaccountingtransactions/ refuses matters where booking is blocked: POST returns HTTP 400 when the referenced matter has the booking of billables blocked, either through the matter's own block_time_entry setting or through its matter status. PUT returns HTTP 400 only when it assigns the transaction to a different matter that is blocked; a transaction whose matter was blocked after it was booked can still be updated.
The read-only is_time_entry_blocked field on /api/v3/matters/ reports the combined result, and ?is_time_entry_blocked=true filters on it.
For more information about Legalsense features, please visit our knowledge base.
Comments
0 comments
Article is closed for comments.