Biom business. API
https://calisma-alaniniz.ornek.comGenel bakış
Biom business. kendi sistemlerinizi ekip iletişimine bağlamanız için üç yol sunar:
- Bot uygulaması. Çalışma alanı yöneticisi Tercihler → Uygulamalar ve otomasyon bölümünden bir uygulama oluşturur. Uygulamanın kendi bot kullanıcısı ve
xbiom-ile başlayan anahtarı olur. Bot mesaj gönderir, olay alır, eğik çizgi komutu ve düğme etkileşimi işler. - Kişisel API anahtarı. Yöneticiler ve yöneticinin izin verdiği üyeler (Yönetim → Üyeler → API) Tercihler → API anahtarları bölümünden, seçtikleri izinlerle sınırlı bir
xbiomu-anahtarı oluşturabilir. Anahtar sahibinin adına ve yalnız onun erişebildiği yerlere erişir. Betikler, CI ve kişisel otomasyonlar içindir. - OAuth 2.0. Başka bir ürün, kullanıcılardan izin alıp onlar adına (izinle sınırlı) bir anahtar edinir. Takvim, CRM ya da proje aracı entegrasyonları içindir.
Tüm istekler ve yanıtlar JSON'dur (Content-Type: application/json). Kanal, mesaj ve kişi kimlikleri tam sayıdır. Zaman damgaları milisaniye cinsinden Unix zamanıdır.
Kimlik doğrulama
Anahtarı her istekte Authorization başlığında gönderin:
curl https://calisma-alaniniz.ornek.com/api/app/auth.test \
-H "Authorization: Bearer xbiom-…"
| Anahtar | Kimin adına | Nereden |
|---|---|---|
xbiom-… | Uygulamanın bot kullanıcısı | Uygulama oluşturulunca bir kez gösterilir; uygulama ayrıntısından yenilenebilir. |
xbiomu-… (kişisel) | Anahtarı oluşturan üye | Tercihler → API anahtarları (yöneticinin izni gerekir). Süresiz ya da 1-365 gün geçerli; izin kaldırılınca geçersiz olur. |
xbiomu-… (OAuth) | İzin veren üye | OAuth kod değişimi sonunda verilir. |
Anahtarlar veritabanında yalnız SHA-256 özetiyle tutulur; kaybederseniz yenisini oluşturun. Anahtar, sahibinin yetkilerinin üstüne çıkamaz: kapsam bir üst sınırdır. Yönetim, hesap, parola, oturum ve anahtar yönetimi uçları API anahtarlarına kapalıdır; bunlar yalnız tarayıcı oturumuyla kullanılır.
İzin kapsamları
Bot uygulamasının izinleri uygulama ayrıntısındaki İzinler bölümünden, kişisel anahtarın izinleri oluşturulurken seçilir. Kapsamı olmayan bir uca yapılan istek 403 döner.
| Kapsam | Ne sağlar |
|---|---|
chat:write | Mesaj gönderme, düzenleme ve silme; anket |
channels:read | Kanalları, üyeleri ve sabitlenenleri görme |
channels:history | Kanal ve ileti dizisi mesajlarını okuma, arama |
channels:join | Açık kanallara katılma ve ayrılma |
channels:write | Kanal oluşturma ve düzenleme, kanala kişi ekleme |
reactions:write | Mesajlara tepki ekleme |
pins:write | Mesaj sabitleme |
users:read | Kişileri, profilleri ve kullanıcı gruplarını görme |
files:read · files:write | Dosyaları listeleme · dosya yükleme |
docs:read · docs:write | Belge ve listeleri okuma · oluşturma ve düzenleme |
communities:read · communities:write | Toplulukları, üyeleri, rolleri ve etkinlikleri görme · rol ve etkinlik yönetimi |
feed:read · feed:write | Akış gönderilerini ve hikâyeleri görme · paylaşma |
reminders:write | Hatırlatıcı kurma |
events:read | Kişisel anahtarla gerçek zamanlı sokete bağlanma |
Web API yöntemleri
Yöntemler /api/app/<yöntem> adresindedir. Okuma yöntemleri GET ve sorgu dizesiyle, diğerleri POST ve JSON gövdeyle çağrılır. Başarılı yanıtta "ok": true bulunur. channel parametresi kanal kimliği, #kanal-adi ya da doğrudan mesaj için @kullanici olabilir.
| Yöntem | Kapsam | Parametreler |
|---|---|---|
GET auth.test | — | Anahtarın türünü (bot / user), kimliği ve kapsamlarını döner. |
POST chat.postMessage | chat:write | channel, text, isteğe bağlı thread (ana mesaj kimliği), blocks |
POST chat.update | chat:write | message, text ve/veya blocks (null düğmeleri kaldırır). Yalnız kendi mesajları. |
POST chat.delete | chat:write | message. Yalnız kendi mesajları. |
POST reactions.add | reactions:write | message, emoji |
POST pins.add · pins.remove | pins:write | message |
POST conversations.join | channels:join | channel (açık kanal) |
POST conversations.create | channels:write | name, isteğe bağlı topic, private |
GET conversations.list | channels:read | — |
GET conversations.info · conversations.members | channels:read | channel |
GET conversations.history | channels:history | channel, isteğe bağlı limit (1-200) |
GET users.list | users:read | — |
GET users.info | users:read | user (kimlik ya da @kullanici) |
curl -X POST https://calisma-alaniniz.ornek.com/api/app/chat.postMessage \
-H "Authorization: Bearer xbiom-…" \
-H "Content-Type: application/json" \
-d '{"channel": "#satis", "text": "Yeni sipariş: *#1042* — 3 kalem, 4.250 TL"}'
Bot, açık bir kanala ilk mesajını gönderdiğinde kanala kendiliğinden katılır. Özel kanallara bir üyenin botu eklemesi gerekir.
REST uçları
Web uygulamasının kullandığı REST uçları da API anahtarlarıyla, kapsama göre kullanılabilir. Bot anahtarı bot kullanıcısı, kişisel anahtar sahibi adına çalışır. Sık kullanılanlar:
| Uç | Kapsam |
|---|---|
GET /api/channels/browse, GET /api/channels/:id, …/members, …/pins, …/files, GET /api/unreads | channels:read |
GET /api/channels/:id/messages?before=&limit=, GET /api/messages/:id/thread, GET /api/search?q= | channels:history |
POST /api/channels/:id/messages ({"body": "…"}), PATCH/DELETE /api/messages/:id, POST /api/channels/:id/polls | chat:write |
POST /api/channels/:id/join · …/leave | channels:join |
POST /api/channels, PATCH /api/channels/:id, POST /api/channels/:id/members | channels:write |
GET /api/users, GET /api/profiles/:kullanici, GET /api/groups | users:read |
GET /api/files · POST /api/files | files:read · files:write |
/api/canvases…, /api/lists… | docs:read (GET) · docs:write |
GET /api/communities…, …/events, POST /api/communities/:id/events | communities:read · communities:write |
GET /api/feed, GET /api/stories, POST /api/posts | feed:read · feed:write |
/api/reminders | reminders:write |
Listede olmayan uçlar API anahtarlarına kapalıdır ve 403 döner.
Hatalar ve hız sınırları
Hatalı isteklerde uygun HTTP durum kodu ve şu gövde döner:
{ "error": "Bu kanalın üyesi değil; önce kanala ekleyin.", "code": "uye-degil" }
| Durum | Anlamı |
|---|---|
400 | Geçersiz parametre |
401 | Anahtar yok, geçersiz, süresi dolmuş ya da geri alınmış |
403 | Kapsam yetersiz, uç anahtarlara kapalı ya da sahibinin yetkisi yok |
404 | Kayıt yok ya da erişilemiyor |
429 | Hız sınırı aşıldı; Retry-After başlığındaki saniye kadar bekleyin |
Her anahtar dakikada en çok 240 istek yapabilir. Mesaj gönderme, dosya yükleme ve webhook uçlarının ayrıca kendi sınırları vardır. Biom'un olay ve komut istekleri 3 saniyede zaman aşımına uğrar.
Olaylar
Uygulama ayrıntısında bir olay adresi girip abone olacağı olayları seçtiğinizde, botun üyesi olduğu kanallardaki olaylar bu adrese imzalı POST olarak gelir. Soket kipi açıksa aynı olaylar canlı bağlantıya da gelir.
| Olay | Ne zaman |
|---|---|
message | Botun üyesi olduğu kanala mesaj yazıldığında (botun kendi mesajları hariç) |
app_mention | Mesajda @bot-adi geçtiğinde |
reaction_added | Bir mesaja tepki eklendiğinde |
member_joined_channel | Kanala biri katıldığında |
{
"type": "event",
"appId": 4,
"eventTime": 1792152000000,
"event": {
"type": "message",
"channel": { "id": 7, "name": "destek", "kind": "public" },
"messageId": 5120,
"parentId": null,
"user": { "id": 12, "username": "deniz", "name": "Deniz Aydın" },
"text": "Fatura PDF'i açılmıyor"
}
}
Olay adresiniz 2xx ile hızlıca yanıt vermelidir; uzun işleri arka planda yapın.
Gerçek zamanlı soket
Herkese açık bir adresiniz yoksa (ör. şirket içi sunucu, yerel geliştirme) uygulama ayrıntısından soket kipini açın. Uygulamanız Biom'a WebSocket ile bağlanır; olaylar, komutlar ve düğme etkileşimleri bu bağlantıdan gelir.
wss://calisma-alaniniz.ornek.com/wsadresine bağlanın.- İlk ileti olarak
{"type": "auth", "token": "xbiom-…"}gönderin. {"type": "ready", "userId": …}gelince bağlantı hazırdır. Anahtar geçersizse bağlantı4001koduyla kapanır.- Bağlantıyı canlı tutmak için 25 saniyede bir düz metin
pinggönderin; sunucupongder.
| İleti türü | İçerik (payload) |
|---|---|
app.event | Olay gövdesinin aynısı |
app.command | Komut isteği; yanıtı responseUrl adresine gönderin |
app.interaction | block_actions isteği; yanıtı responseUrl adresine gönderin |
events:read kapsamlı kişisel anahtarlar da sokete bağlanabilir. Bu durumda sahibinin uygulamada gördüğü canlı olaylar (message.created, message.updated, channel.updated, member.joined vb.) gelir.
İmza doğrulama
Biom'dan gelen her istek (olay, komut, düğme) uygulamanızın imzalama sırrıyla imzalanır. İsteğin gerçekten Biom'dan geldiğini ve değiştirilmediğini doğrulamadan işlemeyin.
X-Biom-Timestamp: isteğin gönderildiği an, saniye cinsinden Unix zamanı.X-Biom-Signature:v1=+ HMAC-SHA256(imzalama sırrı,v1:<zaman>:<ham gövde>), onaltılık.
Ham gövdeyi JSON olarak ayrıştırmadan önce imzalayın, karşılaştırmayı sabit sürede yapın ve 5 dakikadan eski zaman damgalarını reddedin (tekrar saldırısı).
import { createHmac, timingSafeEqual } from "node:crypto";
function biomdanMi(sir, zaman, imza, hamGovde) {
if (Math.abs(Date.now() / 1000 - Number(zaman)) > 300) return false;
const beklenen = "v1=" + createHmac("sha256", sir).update(`v1:${zaman}:${hamGovde}`).digest("hex");
return beklenen.length === imza.length && timingSafeEqual(Buffer.from(beklenen), Buffer.from(imza));
}
Düğmeler ve menüler
chat.postMessage ve chat.update ile mesaja düğme ve açılır menü ekleyebilirsiniz. Bir mesajda en çok 5 satır, satırda en çok 5 öğe olur; action_id mesaj içinde tekil olmalıdır.
{
"channel": "#satin-alma",
"text": "Ali 12 adet monitör talep etti (toplam 54.000 TL).",
"blocks": [{
"type": "actions",
"elements": [
{ "type": "button", "action_id": "onayla", "text": "Onayla", "value": "talep-88", "style": "primary" },
{ "type": "button", "action_id": "reddet", "text": "Reddet", "value": "talep-88", "style": "danger" },
{ "type": "button", "action_id": "ac", "text": "Talebi aç", "url": "https://erp.ornek.com/talep/88" },
{ "type": "select", "action_id": "oncelik", "placeholder": "Öncelik",
"options": [{ "text": "Yüksek", "value": "yuksek" }, { "text": "Normal", "value": "normal" }] }
]
}]
}
Bağlantılı düğmeler (url) yalnız adresi açar. Diğerlerine tıklandığında uygulamanın etkileşim adresine (yoksa olay adresine ya da soket kipinde canlı bağlantıya) imzalı bir istek gider. Düğmenin değeri mesajdaki tanımdan alınır, tarayıcıya güvenilmez.
{
"type": "block_actions",
"user": { "id": 12, "username": "deniz", "name": "Deniz Aydın" },
"channel": { "id": 9, "name": "satin-alma", "kind": "public" },
"message": { "id": 5188, "text": "Ali 12 adet monitör talep etti…", "parentId": null, "blocks": [ … ] },
"action": { "type": "button", "actionId": "onayla", "value": "talep-88", "text": "Onayla" },
"responseUrl": "/api/hooks/response/…",
"actionTime": 1792152000000
}
Yanıt olarak (hemen ya da responseUrl ile) şunlardan birini dönebilirsiniz:
| Yanıt | Etkisi |
|---|---|
{"replace_original": true, "text": "Deniz onayladı ✓", "blocks": null} | Asıl mesajı değiştirir; blocks: null düğmeleri kaldırır |
{"delete_original": true} | Asıl mesajı siler |
{"response_type": "in_channel", "text": "…"} | Kanala yeni bir bot mesajı yazar |
{"text": "…"} | Yalnız tıklayan kişinin göreceği geçici bir yanıt |
Eğik çizgi komutları
Uygulamaya /stok gibi bir komut ekleyin. Bir üye komutu yazdığında komut adresine (soket kipinde adres girmeden canlı bağlantıya) imzalı istek gider:
{
"type": "command",
"command": "/stok",
"text": "A-1042",
"user": { "id": 12, "username": "deniz", "name": "Deniz Aydın" },
"channel": { "id": 7, "name": "depo", "kind": "public" },
"parentId": null,
"responseUrl": "/api/hooks/response/…"
}
3 saniye içinde JSON ({"text": "…"}, kanala yazmak için "response_type": "in_channel") ya da düz metin dönün. Daha uzun süren işlerde boş yanıt verin, sonucu sonra responseUrl adresine POST edin. Yanıt adresi 30 dakika geçerlidir ve en çok 5 kez kullanılabilir. Göreli adresin başına çalışma alanı adresini ekleyin.
Gelen webhook'lar
En basit entegrasyon: uygulama ayrıntısından bir kanala webhook ekleyin, size verilen adrese {"text": "…"} gönderin. Anahtar ya da imza gerekmez; adresin kendisi gizlidir.
curl -X POST https://calisma-alaniniz.ornek.com/api/hooks/12/AbC… \
-H "Content-Type: application/json" \
-d '{"text": "Gece yedeği tamamlandı (2,4 GB, 6 dk)."}'
Mesajlar *kalın*, _eğik_, `kod`, bağlantı ve @kullanici biçimlerini destekler. Her webhook dakikada en çok 60 istek kabul eder.
OAuth 2.0
Başka bir ürünün Biom kullanıcıları adına çalışması için uygulama ayrıntısındaki OAuth bölümünden dönüş adreslerini kaydedin. Size bir client_id ve bir kez gösterilen client_secret verilir. Akış standart yetkilendirme kodu akışıdır:
- Kullanıcıyı izin ekranına yönlendirin:
https://calisma-alaniniz.ornek.com/oauth/authorize?client_id=biom_…&redirect_uri=https%3A%2F%2Fornek.com%2Fgeri&scope=chat:write%20users:read&state=…scopeboşluk ya da virgülle ayrılır ve uygulamanın izinleri içinde olmalıdır.state'i oturumunuzla eşleştirip dönüşte denetleyin. - Kullanıcı giriş yapar ve izin verirse
redirect_uri?code=…&state=…adresine döner. Reddederseerror=access_deniedgelir. Kod 10 dakika geçerlidir ve tek kullanımlıktır. - Kodu sunucunuzda anahtara çevirin (istemci sırrını tarayıcıya vermeyin):
İstemci kimliğini HTTP Basic ile de gönderebilirsiniz. Yanıt:curl -X POST https://calisma-alaniniz.ornek.com/api/oauth/token \ -H "Content-Type: application/json" \ -d '{"grant_type": "authorization_code", "code": "…", "redirect_uri": "https://ornek.com/geri", "client_id": "biom_…", "client_secret": "xbiomcs-…"}'{"access_token": "xbiomu-…", "token_type": "Bearer", "scope": "chat:write users:read", "user": {…}}. Hatalardacodealanıinvalid_client,invalid_grantya daunsupported_grant_typeolur.
Kullanıcı verdiği izni Tercihler → Bağlı uygulamalar bölümünden istediği an geri alabilir. İstemci sırrı yenilendiğinde ya da OAuth kapatıldığında o uygulamaya verilmiş tüm anahtarlar geçersiz olur.
JavaScript SDK
Bağımlılığı olmayan tek dosya. Node 22+, Deno, Bun, Cloudflare Workers ve tarayıcıda çalışır. biom.mjs dosyasını indirin ve projenize ekleyin.
import { Biom } from "./biom.mjs";
const biom = new Biom(process.env.BIOM_TOKEN, { baseUrl: "https://calisma-alaniniz.ornek.com" });
await biom.chat.postMessage({ channel: "#genel", text: "Merhaba!" });
const { channels } = await biom.conversations.list();
await biom.call("users.info", { user: "@deniz" }); // herhangi bir Web API yöntemi
await biom.request("GET", "/api/channels/7/messages"); // REST uçları
Soket kipinde bot
İşleyicinin döndürdüğü yanıt, yanıt adresine kendiliğinden gönderilir. Bağlantı koparsa SDK yeniden bağlanır.
biom.listen({
onEvent: async (event) => {
if (event.type === "app_mention") await biom.chat.postMessage({ channel: event.channel.id, thread: event.messageId, text: "Bakıyorum 👀" });
},
onCommand: (cmd) => ({ text: `${cmd.text} için stok: 42 adet` }),
onInteraction: (p) => ({ replace_original: true, text: `${p.user.name} onayladı ✓`, blocks: null }),
});
HTTP ile olay ve komut almak
createHandler imzayı doğrular ve isteği türüne göre yönlendirir. Workers, Deno ve Bun'da doğrudan, Node'da toNodeListener ile kullanılır.
import http from "node:http";
import { createHandler, toNodeListener } from "./biom.mjs";
const handler = createHandler({
signingSecret: process.env.BIOM_SIGNING_SECRET,
onEvent: (event) => console.log(event.type, event.text),
onCommand: (cmd) => ({ response_type: "in_channel", text: `Sipariş ${cmd.text} kargoda.` }),
onInteraction: (p) => ({ replace_original: true, text: "Talep onaylandı ✓", blocks: null }),
});
http.createServer(toNodeListener(handler)).listen(3000);
OAuth
const url = Biom.authorizeUrl({ baseUrl, clientId, redirectUri, scope: ["chat:write"], state });
// … kullanıcı dönüş adresine geldiğinde:
const { access_token, user } = await Biom.exchangeCode({ baseUrl, clientId, clientSecret, code, redirectUri });
Hatalar BiomError olarak fırlatılır (status, code, retryAfter). 429 yanıtlarında SDK Retry-After kadar bekleyip iki kez yeniden dener. İmzayı elle doğrulamak için verifySignature({ secret, body, timestamp, signature }) kullanın.
Komut satırı aracı
biom-cli.mjs dosyasını biom.mjs ile aynı klasöre indirin. Node 22+ gerekir.
export BIOM_URL=https://calisma-alaniniz.ornek.com
export BIOM_TOKEN=xbiomu-…
node biom-cli.mjs auth # anahtarı ve izinleri gösterir
node biom-cli.mjs send "#duyurular" "Sunucu bakımı 22:00'de"
node biom-cli.mjs call conversations.history channel=#genel limit=5
node biom-cli.mjs get /api/unreads
node biom-cli.mjs listen # canlı olaylar, satır başına bir JSON
node biom-cli.mjs verify "$SIR" 1792152000 v1=… < govde.json
CI hatta bildirim göndermek için send komutunu kullanabilirsiniz. Bunun için yalnız chat:write kapsamlı bir kişisel anahtar ya da bot anahtarı yeterlidir.