Skip to main content
Upcoming release — Zylon 1.58These docs are published ahead of release so you can prepare your API integrations. The release image is not yet available. For installations running 1.57, use the 1.57 documentation.
Zylon 1.58 unifies artifact routes and separates workspace memberships from accounts. Use this guide to update integrations built against 1.57. It covers changes to existing Workspace APIs, plus the new server tool content blocks returned in chat messages by both the Workspace and ZylonGPT APIs.
The legacy artifact, integration, and member routes are deprecated in 1.58, with removal planned for 1.59. Other accepted aliases have their own compatibility notes below. Use the current 1.58 routes for new or maintained integrations.If your integration depends on user identity, creator IDs, or creator filters, migrate the affected calls to the current API and update your identity mappings. A working legacy URL does not restore the 1.57 identity model. Creator fields now identify accounts; membership routes still use workspace-member IDs. Follow the saved user-ID migration before relying on existing lookups, comparisons, or filters.

Prerequisites

  • An API token and your Zylon hostname. See Workspace Token Management.
  • Send Authorization: Bearer {API_TOKEN} and x-org: {org_slug} for workspace requests.
  • Send Content-Type: application/json for JSON bodies. Let your HTTP client set the boundary for multipart requests.
Paths in the tables below are relative to https://{BASE_URL}/api/v1.

Artifact routes

Replace the project or organization artifact prefix with /app/artifact. Supply project ownership or filtering explicitly where needed.
When using x-org, do not also send organization_id. Without x-org, specifying organization_id requires an Operator or SuperAdmin. Creating organization artifacts requires AppAdmin or higher; Link artifacts require a project.

Creation bodies

The current JSON create field content contains Base64-encoded file or text bytes. It replaces the old plain-text raw_content input. For example, UTF-8 Hello becomes SGVsbG8=.
POST /app/project/{projectID}/artifact
Other type-specific fields retain their current rules. See the complete artifact request fields and types.

Update bodies

The old update content was Base64 binary editor state. The current JSON update content is plain UTF-8 text, such as Markdown. Export the editor document to Markdown; merely decoding its Base64 bytes does not produce document text.
PUT /app/project/{projectID}/artifact/{artifactID}
{BASE64_EDITOR_STATE} represents your existing encoded editor document.
Create and update use different encodings: Base64 for JSON creation, plain text for JSON updates. Do not send the old editor-state string to the current update route; it would be treated as literal text.
The same update format applies to update-validation and each artifacts[].update entry in bulk updates. Bulk entries still use artifactId and update. Remove plain_text_content; it was separate search text, and current search text is derived from the document. For file replacement, use multipart file_data on the current update route. See updating artifacts.

What legacy artifact requests still support

  • JSON creation, validation, and retry accept raw_content; multipart creation also accepts file bytes. Legacy creation takes the project from the URL and rejects body project_id, organization_id, and new JSON content.
  • Legacy JSON updates convert Base64 editor state to Markdown before saving. This requires the deployment’s document conversion service to be available. Binary content can be supplied with or without plain_text_content; that field alone does not replace document content.
  • Legacy update, update-validation, and bulk update accept JSON only. Use the current endpoint for multipart replacement.
  • A create request combining raw_content and a file is rejected: both cannot be preserved in the single current content field. Send one content representation.
  • Unknown fields and invalid legacy field types are rejected. Organization creation accepts only scopes for the selected organization.

Artifact responses and selection

Legacy artifact responses keep has_content, always false: this field described the old binary editor content, not whether a file exists. Original editor bytes cannot be reconstructed, so content is null/omitted. On legacy artifact detail requests, add include_content=true to receive available UTF-8 text as raw_content. The default is false; lists and mutation responses do not include text. Whitespace and empty text are preserved. Non-text files and invalid UTF-8 have no raw_content. Current download permissions apply; disabled downloads return 403, and missing stored files return the current download error.
Null fields are omitted. No Base64 editor content is generated from the text.
Current artifact responses omit these legacy content fields. Use /app/artifact/{artifactID}/download for stored content. /app/artifact/{artifactID}/parsed-content returns extracted text and requires an initialized vector index. Download returns a presigned URL by default; Content-Disposition: attachment returns file bytes. Both modes are also supported on legacy download URLs. Artifact created_by now represents an account. Update code that reads creator details or compares creator IDs; see account IDs and renamed fields. scopes[].ws_auto_select and scopes[].enabled already existed in released 1.57 versions and remain supported, including enabled: false. The older top-level ws_auto_select flag is not accepted. Skill uploads still use file_data; there is no separate skill-body migration here. See artifact scopes.

Workspace members

User data is unified at the account level: identity, name, email, and profile picture belong to the account. The former user becomes a workspace membership, holding the account’s roles, permissions, and active/inactive state within that workspace. Replace /app/user with /app/member. IDs in these paths remain workspace-member IDs, not account IDs. Legacy /app/user list, detail, create, role-update, activate, and deactivate responses still expose top-level name, email, and available profile_picture, taken from the account’s current profile. Membership id, org_id, account_id, state, roles, and created_at remain available. Removed job-position data cannot be recovered and is null/omitted. These response fields do not restore profile updates through the old member route. GET /app/me keeps its URL but returns the new member model too. Names, email, and profile pictures are account data; they are no longer top-level member fields. Request include=Account on member list, member details, or /app/me to receive the nested account.
Workspace roles: AppGuest, AppMember, AppAdmin, AppOwner.
Update account profile fields with POST /account/{accountId} (me is accepted for your own account), instead of the member update endpoint. The former job_position_name and job_position_description member fields are removed; they are not part of the account model.

Account IDs and renamed fields

Migrate saved user IDs

If your client saved userId from a 1.57 /app/user response’s id, that value is a workspace-member ID. Do not replace every userId with accountId: these identify different records. One account can have different member IDs in different organizations.
  1. Keep the saved member ID and its organization context. Use the current member endpoint to read the linked account ID:
account_id is returned without an include parameter. Add include=Account when you also need the account profile; see the complete member response.
  1. Store both IDs with distinct names. Use account_id to compare against artifact, thread, interaction, and issue created_by.id, and for artifact or issue created_by filters. Keep the member id for /app/member/{wsMemberId}, project membership, ownership transfer, and chat metadata.ws_member_id.
  2. Update affected calls to current routes and canonical field names, then check your stored joins and filters. For example, an artifact creator filter must use created_by={accountId}; a project-member request still uses ws_member_id: "{wsMemberId}".
For your own identity, GET /api/v1/app/me returns the same id and account_id distinction. To migrate a directory, paginate /app/member separately for each organization and build a member-ID-to-account-ID mapping. If your application needs a workspace-member ID for a creator account, resolve that account’s membership in the selected organization; an account ID alone does not identify one workspace membership.

What legacy aliases preserve

Legacy /app/user reads can restore selected profile fields such as name and email, but their id remains a member ID and their account_id remains an account ID. Legacy artifact creator objects already use account IDs. include=User on supported creator queries selects account data; it does not restore the old workspace-user object or convert creator IDs. Use legacy aliases only as a temporary bridge for the request shapes documented in this guide. If your integration needs the old user-ID relationships, creator filters, or profile-update behavior, migrate to the current API and the account/member model above. Changing only the URL or field name is insufficient.

Use canonical field names

The temporary aliases below accept selected old input names. Responses keep the current model and field names; aliases do not convert member IDs to account IDs. See project members, ownership transfer, and issue filters for complete current bodies and responses.

Chats and threads

Move project chat to the unified route

Replace POST /app/project/{projectID}/chat with POST /app/chat and move the project selector into the body. Use a wrapped pgpt message request (private_gpt remains an input alias). The current route also accepts a legacy flat message request for workspace context, but project and artifact selectors require the wrapper. /app/chat/validate takes the flat message request.
The current /app/chat response is always SSE, including when pgpt.stream is false. The retained project-chat URL returns JSON when that flag is false and SSE when it is true. Update clients that expect a JSON response before switching URLs. No removal version is assigned to the project-chat alias.
For explicit artifact selection, use artifacts.document, artifacts.connector, artifacts.skill, or artifacts.agent_flow. Each is an array of selectors with scope (organization or project), optional all_artifacts, and optional artifacts_ids (note the plural spelling). For example:
This is a partial request body to combine with pgpt and, for project scope, project_id. Do not send the old reference examples’ top-level artifact_ids or all_artifacts: unknown fields are ignored, so they do not select artifacts. A category cannot repeat the same scope or combine all_artifacts: true with nonempty artifacts_ids. See chat requests.

Thread files and read state

1.58 adds raw file writes with PUT /app/thread/{threadID}/put-file/{path...}. Send bytes as the body. Multipart POST /app/thread/{threadID}/upload-file still uses file and now accepts optional path and namespace. Uploads, raw writes, and downloads select session (default), artifacts, or skills with namespace; downloads also accept disposition=attachment (default) or inline. See thread files for upload, download, and MDX artifact conversion. On project thread lists, request include=ReadState to receive read_state.last_read_at and read_state.has_unread_response. A new thread created by another account may also count as unread. Listing interactions with GET /app/thread/{threadID}/interaction now advances the caller’s read checkpoint through the completed responses returned. Clients that poll this endpoint can therefore clear unread state; account for that side effect in notification and polling logic.

Filesystem requests

Credential validation requires the current nested body on both URLs. Flat legacy credentials are not adapted.
This operation returns a boolean. See filesystem validation for the complete request example. Integration ingestion uses the unified artifact /ingest route and a body project_id, as described above.

Server tool content blocks

In 1.57, every tool call in a message came back as a tool_use block followed by a tool_result block. That was true whether Zylon ran the tool or your application did. In 1.58, tools that Zylon runs on the server use the Anthropic Messages API server tool format instead. Tools that your application runs (custom tools) have not changed and still use tool_use and tool_result. The change affects message content in streamed events, stored thread interactions, and /messages responses. Update any code that finds tool calls by checking type == "tool_use" or type == "tool_result".
  • server_tool_use.name is the tool name from the request. Workspace chats send the web fetch tool as web_extract, so its calls appear as web_extract; ZylonGPT API clients see whichever name they sent (web_extract or web_fetch). Match on the result block type (web_fetch_tool_result) rather than the name.
  • Server tool call IDs start with srvtoolu_. Client tool call IDs start with tool_. The result’s tool_use_id points to the call ID, as it did before.
  • Zylon has already run server tools, so do not send results back for them. stop_reason: "tool_use" still applies only to tools your application runs.
  • The block shapes follow the Anthropic server tool format, so Anthropic SDKs can parse them directly. Ignore any fields you do not recognize, because Zylon may add extra ones.

Migration rules

  • Generic server tools (server_tool_result): only the block type values and the ID prefix change. content and is_error work as before, so you can reuse your 1.57 parser.
  • Web and code execution tools: content is now a typed object (or a list of typed objects for web search) instead of a list of text blocks. These blocks have no is_error field. To detect a failure, check whether content.type ends in _error, then read content.error_code.
  • Failures that 1.57 returned as text: in 1.57, the text editor tools reported failures as a successful tool_result whose text started with Error:. In 1.58, they return an error object.
  • Non-zero exit codes: a bash command that exits with a non-zero code is not an error in either version. In 1.58, read return_code instead of parsing exit_code: from the text.

Migration examples by tool

Each example shows the call block and the result block for a successful call and a failed call. The IDs, inputs, and result text are only examples.
Error:
Error:
A command with a non-zero exit code:
Error (the tool could not run):
In 1.57, each operation was a separate tool. In 1.58, they are all text_editor_code_execution, and the operation is given in input.command. The other input fields keep their names. For insert, 1.58 accepts both insert_text and new_str.
view:
create:
str_replace:
insert:
Error. File errors came back as a successful result whose text started with Error::
Error:
Error:
Error:
Error:
Error:
Error:
Skill tools return JSON as text. If a skill is not found, the tool returns an error key in the JSON and keeps is_error: false.
Error:
MCP tools keep the MCP server’s tool name and return the content blocks the MCP server produced.
Error:
Nothing changes for tools that your application defines and runs. The response stops with stop_reason: "tool_use", your application runs the tool, and it sends back a tool_result block, as in 1.57.

Requests with the Zylon extension enabled

When a request enables the Zylon extension (system.extensions includes zylon):
  • web_search and web_fetch results are returned as a plain tool_result block, as the examples above show. The call block is still server_tool_use, and the call ID still starts with srvtoolu_.
  • Error objects in bash_code_execution_tool_result and text_editor_code_execution_tool_result include a detail field that contains the underlying error.
  • Zylon-specific blocks, such as source, are kept in server_tool_result content.

Sending conversation history

You can send server_tool_use and server tool result blocks back in messages exactly as you received them. Zylon converts them internally, so if you forward previous assistant turns unchanged, you do not need to change anything. History that uses the 1.57 tool_use and tool_result blocks is still accepted.

Before upgrading your client

  1. Replace deprecated URLs and move project selectors to the appropriate query or body fields.
  2. Use Base64 bytes for JSON artifact creation, plain text for updates, and file_data for multipart files.
  3. Update response readers for account/member separation and removed inline artifact content. Audit stored user/account IDs, joins, comparisons, and filters even when existing calls succeed.
  4. Replace creator filters with account IDs and use canonical field/include names.
  5. Update message parsers to handle server_tool_use and the server tool result blocks, and only return tool_result for your own custom tools.
  6. Adapt chat wrappers, scoped artifact selectors, SSE handling, thread files, and read-state polling.
  7. Test against 1.58, including role permissions, validation, content conversion, and filesystem validation. Legacy URLs use current authorization, response, and service behavior; they do not recreate every 1.57 behavior.