Prerequisites
- An API token and your Zylon hostname. See Workspace Token Management.
- Send
Authorization: Bearer {API_TOKEN}andx-org: {org_slug}for workspace requests. - Send
Content-Type: application/jsonfor JSON bodies. Let your HTTP client set the boundary for multipart requests.
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.
Endpoint parameters
Endpoint parameters
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 fieldcontent contains Base64-encoded file or text bytes. It replaces the old plain-text raw_content input. For example, UTF-8 Hello becomes SGVsbG8=.
- 1.57 request
- 1.58 request
POST /app/project/{projectID}/artifactRequest body changes
Request body changes
Update bodies
The old updatecontent 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.
- 1.57 request
- 1.58 request
PUT /app/project/{projectID}/artifact/{artifactID}{BASE64_EDITOR_STATE} represents your existing encoded editor document.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 bodyproject_id,organization_id, and new JSONcontent. - 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_contentand 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 keephas_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.
Legacy content fields (partial response)
Legacy content fields (partial response)
content is generated from the text./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.
Endpoint parameters
Endpoint parameters
Workspace roles:
AppGuest, AppMember, AppAdmin, AppOwner.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.
Current member response
Current member response
Account IDs and renamed fields
Migrate saved user IDs
If your client saveduserId 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.
- Keep the saved member ID and its organization context. Use the current member endpoint to read the linked account ID:
Endpoint parameters
Endpoint parameters
ID mapping response (selected fields)
ID mapping response (selected fields)
account_id is returned without an include parameter. Add include=Account when you also need the account profile; see the complete member response.- Store both IDs with distinct names. Use
account_idto compare against artifact, thread, interaction, and issuecreated_by.id, and for artifact or issuecreated_byfilters. Keep the memberidfor/app/member/{wsMemberId}, project membership, ownership transfer, and chatmetadata.ws_member_id. - 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 usesws_member_id: "{wsMemberId}".
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
ReplacePOST /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.
Endpoint parameters
Endpoint parameters
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:
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 withPUT /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.
Request body
Request body
/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 atool_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.nameis the toolnamefrom the request. Workspace chats send the web fetch tool asweb_extract, so its calls appear asweb_extract; ZylonGPT API clients see whichever name they sent (web_extractorweb_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 withtool_. The result’stool_use_idpoints 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 blocktypevalues and the ID prefix change.contentandis_errorwork as before, so you can reuse your 1.57 parser. - Web and code execution tools:
contentis now a typed object (or a list of typed objects for web search) instead of a list oftextblocks. These blocks have nois_errorfield. To detect a failure, check whethercontent.typeends in_error, then readcontent.error_code. - Failures that 1.57 returned as text: in 1.57, the text editor tools reported failures as a successful
tool_resultwhose text started withError:. 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_codeinstead of parsingexit_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.web_search
web_search
- 1.57
- 1.58
- 1.58 with Zylon extension
web_extract (web fetch)
web_extract (web fetch)
- 1.57
- 1.58
- 1.58 with Zylon extension
bash → bash_code_execution
bash → bash_code_execution
- 1.57
- 1.58
- 1.58 with Zylon extension
view, create, str_replace, insert → text_editor_code_execution
view, create, str_replace, insert → text_editor_code_execution
In 1.57, each operation was a separate tool. In 1.58, they are all Error. File errors came back as a successful result whose text started with
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.- 1.57
- 1.58
- 1.58 with Zylon extension
view:create:str_replace:insert:Error::semantic_search
semantic_search
- 1.57
- 1.58
summarize
summarize
- 1.57
- 1.58
tabular_analysis
tabular_analysis
- 1.57
- 1.58
database_query
database_query
- 1.57
- 1.58
present_files
present_files
- 1.57
- 1.58
present_server
present_server
- 1.57
- 1.58
Skill tools (load_skill, unload_skill, list_skills)
Skill tools (load_skill, unload_skill, list_skills)
Skill tools return JSON as text. If a skill is not found, the tool returns an Error:
error key in the JSON and keeps is_error: false.- 1.57
- 1.58
MCP tools
MCP tools
MCP tools keep the MCP server’s tool name and return the content blocks the MCP server produced.Error:
- 1.57
- 1.58
Custom tools (unchanged)
Custom tools (unchanged)
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_searchandweb_fetchresults are returned as a plaintool_resultblock, as the examples above show. The call block is stillserver_tool_use, and the call ID still starts withsrvtoolu_.- Error objects in
bash_code_execution_tool_resultandtext_editor_code_execution_tool_resultinclude adetailfield that contains the underlying error. - Zylon-specific blocks, such as
source, are kept inserver_tool_resultcontent.
Sending conversation history
You can sendserver_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
- Replace deprecated URLs and move project selectors to the appropriate query or body fields.
- Use Base64 bytes for JSON artifact creation, plain text for updates, and
file_datafor multipart files. - 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.
- Replace creator filters with account IDs and use canonical field/include names.
- Update message parsers to handle
server_tool_useand the server tool result blocks, and only returntool_resultfor your own custom tools. - Adapt chat wrappers, scoped artifact selectors, SSE handling, thread files, and read-state polling.
- 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.