Images via API
The Senler server can download an image from a link, store its own copy, and prepare it for the target resource. Integrations and agents using MCP do not need to open a browser, send a binary file through PUT, or confirm the upload separately.
Specify the source
Pass exactly one field in the JSON request:
url: an HTTP(S) image address accessible to the server, including astorage_urlreturned by image generation;attachment_id: the ID of a ready media attachment from a message or generation. Access to the source dialog is required even when you can edit the target resource.
attachment_id is not the fileId from a confirmed upload. To import such an upload into another resource, use its returned url.
You can also pass file_name and idempotency_key. The name does not change the format: the server checks the file contents.
Choose the destination
All methods below use POST. Replace identifiers in braces with the target resource IDs. Authorization and available actions depend on token permissions.
Avatars and application artwork are applied as soon as the import succeeds:
- project:
/api/projects/{projectId}/avatar/from-url; - channel:
/api/channels/{id}/avatar/from-url; - current user:
/api/cabinet/profile/avatar/from-url; - live agent profile:
/api/agents/{agentId}/avatar/from-url; - agent draft only:
/api/agents/{agentId}/draft/avatar/from-url, followed by separate publication; - automation:
/api/automations/{automationId}/avatar/from-url; - application icon:
/api/apps/{id}/icon/from-url; - application cover:
/api/apps/{id}/cover/from-url.
Channel avatars cannot be changed manually for Telegram, VK, MAX, and Discord: they are updated from the platform. This method is available for the other types. Channels also support the previous field name imageUrl; supply only one source: imageUrl, url, or attachment_id.
A user avatar requires a session or user OAuth with can_manage_profile. A project API key cannot be used; through MCP, this operation is available in the user server.
Application covers are fitted to 706×398 pixels. The default fit: "contain" preserves the entire image with padding; fit: "cover" fills the cover by cropping the edges.
Landing images and step icons must then be attached to their content:
- landing:
/api/landings/{landingId}/assets/from-url; - agent landing:
/api/agents/{agentId}/landing/assets/from-url; - application step icon:
/api/apps/{appId}/automation-steps/icon/from-url.
For a landing, use the returned url when saving a block, background, icon, or banner. For a step icon, pass the returned key as icon_asset_key. Uploading does not save the block or publish the landing or step.
Message and broadcast attachments return a fileId for the next action:
- channel:
/api/dialogs/attachments/channels/{channelId}/from-url; - dialog:
/api/dialogs/attachments/dialogs/{dialogId}/from-url; - test draft:
/api/dialogs/attachments/projects/{projectId}/drafts/{draftId}/from-url; - automation:
/api/automations/{automationId}/attachments/from-url; - broadcast:
/api/deliveries/attachments/from-url, withproject_idin JSON.
Pass fileId to the relevant method for sending a message or saving step/broadcast attachments. Import itself does not send anything or start a test, automation, or broadcast.
The knowledge base and application documentation save the file to the selected folder:
- knowledge base:
/api/knowledge-base/files/from-url, withproject_idin JSON; - application documentation:
/api/apps/{appId}/documentation/files/from-url.
Available fields include folder_id, title, locale (ru or en), and image_recognition_mode. The default language is ru, and recognition is disabled: image_recognition_mode: "none". Enabled recognition runs in the knowledge base and uses project credits; importing an image does not mean it has already been recognized.
Avatar example
This server-side JavaScript example uses an API key or OAuth token. Do not put the secret token in website code:
const response = await fetch(
`https://api.senler.io/api/projects/${projectId}/avatar/from-url`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SENLER_API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
url: imageUrl,
file_name: "project-logo",
idempotency_key: "project-logo-v1",
}),
},
);
if (!response.ok) throw new Error(`Image import failed: ${response.status}`);
const result = await response.json();
Your integration supplies projectId and imageUrl. For MCP, find the target resource's import method and read its parameters: for example, ProjectsAvatarController_importFromUrl sets the project avatar, while AgentsAvatarController_importDraftFromUrl only changes the agent draft. These methods are available in Senler.io MCP and user MCP with the appropriate permissions.
Limits and retries
Avatars, application artwork, and landings accept PNG, JPEG, and WebP. Message, automation, and broadcast attachments, the knowledge base, and application documentation also accept GIF. Most methods allow up to 20 MB and 40 megapixels; animation frames count toward the limit. Landings have a separate limit of 10 MB and 8000 pixels per side, still no more than 40 megapixels. Project storage limits may be stricter.
When retrying the same request, reuse the original idempotency_key with the same parameters. A successful result is retained for 24 hours. Different parameters with the same key are rejected.
If the API reports that the change may already have been applied, read the target resource first. Do not create a new key to bypass this conflict: you could apply an already completed change again.