curl --request POST \
--url https://dash.dmly.io/api/agency/v1/workspaces/{workspace}/channels/telegram \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"bot_token": "123456789:AAbbCCddEEffGGhhIIjjKKllMMnnOOpp",
"name": "Sparkle Cleaning"
}
'import requests
url = "https://dash.dmly.io/api/agency/v1/workspaces/{workspace}/channels/telegram"
payload = {
"bot_token": "123456789:AAbbCCddEEffGGhhIIjjKKllMMnnOOpp",
"name": "Sparkle Cleaning"
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
bot_token: '123456789:AAbbCCddEEffGGhhIIjjKKllMMnnOOpp',
name: 'Sparkle Cleaning'
})
};
fetch('https://dash.dmly.io/api/agency/v1/workspaces/{workspace}/channels/telegram', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://dash.dmly.io/api/agency/v1/workspaces/{workspace}/channels/telegram",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'bot_token' => '123456789:AAbbCCddEEffGGhhIIjjKKllMMnnOOpp',
'name' => 'Sparkle Cleaning'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://dash.dmly.io/api/agency/v1/workspaces/{workspace}/channels/telegram"
payload := strings.NewReader("{\n \"bot_token\": \"123456789:AAbbCCddEEffGGhhIIjjKKllMMnnOOpp\",\n \"name\": \"Sparkle Cleaning\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://dash.dmly.io/api/agency/v1/workspaces/{workspace}/channels/telegram")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"bot_token\": \"123456789:AAbbCCddEEffGGhhIIjjKKllMMnnOOpp\",\n \"name\": \"Sparkle Cleaning\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://dash.dmly.io/api/agency/v1/workspaces/{workspace}/channels/telegram")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"bot_token\": \"123456789:AAbbCCddEEffGGhhIIjjKKllMMnnOOpp\",\n \"name\": \"Sparkle Cleaning\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "55555555-5555-5555-5555-555555555555",
"name": "Telegram · @sparkle_bot",
"platform": "telegram",
"handle": "@sparkle_bot",
"status": "connected",
"connected": true,
"created_at": "2026-10-06T12:04:11+00:00"
},
"meta": {
"webhook_registered": true
}
}{
"message": "<string>"
}{
"message": "<string>"
}{
"message": "<string>"
}{
"message": "<string>",
"errors": {}
}{
"message": "<string>"
}{
"message": "<string>"
}Connect a Telegram bot.
Telegram has no consent screen, so there is no hosted session: your app collects the customer’s BotFather bot token and sends it here from your backend. DMLY validates it with Telegram, creates the channel, points the bot’s webhook at DMLY and returns the channel, with meta.webhook_registered. Returns 201 for a new bot and 200 when the same bot is already connected to this sub-account (a new token for it refreshes the channel in place). Returns 422 with an error on bot_token when Telegram rejects the token or the bot is connected to another DMLY workspace, 422 on channel when the plan has no room, and 403 when Channel Connect is not enabled for your agency or the sub-account is suspended. The token is never returned.
curl --request POST \
--url https://dash.dmly.io/api/agency/v1/workspaces/{workspace}/channels/telegram \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"bot_token": "123456789:AAbbCCddEEffGGhhIIjjKKllMMnnOOpp",
"name": "Sparkle Cleaning"
}
'import requests
url = "https://dash.dmly.io/api/agency/v1/workspaces/{workspace}/channels/telegram"
payload = {
"bot_token": "123456789:AAbbCCddEEffGGhhIIjjKKllMMnnOOpp",
"name": "Sparkle Cleaning"
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
bot_token: '123456789:AAbbCCddEEffGGhhIIjjKKllMMnnOOpp',
name: 'Sparkle Cleaning'
})
};
fetch('https://dash.dmly.io/api/agency/v1/workspaces/{workspace}/channels/telegram', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://dash.dmly.io/api/agency/v1/workspaces/{workspace}/channels/telegram",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'bot_token' => '123456789:AAbbCCddEEffGGhhIIjjKKllMMnnOOpp',
'name' => 'Sparkle Cleaning'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://dash.dmly.io/api/agency/v1/workspaces/{workspace}/channels/telegram"
payload := strings.NewReader("{\n \"bot_token\": \"123456789:AAbbCCddEEffGGhhIIjjKKllMMnnOOpp\",\n \"name\": \"Sparkle Cleaning\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://dash.dmly.io/api/agency/v1/workspaces/{workspace}/channels/telegram")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"bot_token\": \"123456789:AAbbCCddEEffGGhhIIjjKKllMMnnOOpp\",\n \"name\": \"Sparkle Cleaning\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://dash.dmly.io/api/agency/v1/workspaces/{workspace}/channels/telegram")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"bot_token\": \"123456789:AAbbCCddEEffGGhhIIjjKKllMMnnOOpp\",\n \"name\": \"Sparkle Cleaning\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "55555555-5555-5555-5555-555555555555",
"name": "Telegram · @sparkle_bot",
"platform": "telegram",
"handle": "@sparkle_bot",
"status": "connected",
"connected": true,
"created_at": "2026-10-06T12:04:11+00:00"
},
"meta": {
"webhook_registered": true
}
}{
"message": "<string>"
}{
"message": "<string>"
}{
"message": "<string>"
}{
"message": "<string>",
"errors": {}
}{
"message": "<string>"
}{
"message": "<string>"
}Authorizations
Your agency API key (dmly_ag_…). It authenticates the acting agency and scopes every request to that agency's own sub-accounts and plans.
Path Parameters
Workspace id.
Body
Response
The same bot, already connected: its channel, refreshed.
Was this page helpful?

