Geliştiriciler

Biom business. API

API sürümü: v1SDK: 0.1.0Adres: https://calisma-alaniniz.ornek.com

Genel bakış

Biom business. kendi sistemlerinizi ekip iletişimine bağlamanız için üç yol sunar:

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-…"
AnahtarKimin adınaNereden
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 üyeTercihler → 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 üyeOAuth 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.

KapsamNe sağlar
chat:writeMesaj gönderme, düzenleme ve silme; anket
channels:readKanalları, üyeleri ve sabitlenenleri görme
channels:historyKanal ve ileti dizisi mesajlarını okuma, arama
channels:joinAçık kanallara katılma ve ayrılma
channels:writeKanal oluşturma ve düzenleme, kanala kişi ekleme
reactions:writeMesajlara tepki ekleme
pins:writeMesaj sabitleme
users:readKişileri, profilleri ve kullanıcı gruplarını görme
files:read · files:writeDosyaları listeleme · dosya yükleme
docs:read · docs:writeBelge ve listeleri okuma · oluşturma ve düzenleme
communities:read · communities:writeToplulukları, üyeleri, rolleri ve etkinlikleri görme · rol ve etkinlik yönetimi
feed:read · feed:writeAkış gönderilerini ve hikâyeleri görme · paylaşma
reminders:writeHatırlatıcı kurma
events:readKiş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öntemKapsamParametreler
GET auth.test—Anahtarın türünü (bot / user), kimliği ve kapsamlarını döner.
POST chat.postMessagechat:writechannel, text, isteğe bağlı thread (ana mesaj kimliği), blocks
POST chat.updatechat:writemessage, text ve/veya blocks (null düğmeleri kaldırır). Yalnız kendi mesajları.
POST chat.deletechat:writemessage. Yalnız kendi mesajları.
POST reactions.addreactions:writemessage, emoji
POST pins.add · pins.removepins:writemessage
POST conversations.joinchannels:joinchannel (açık kanal)
POST conversations.createchannels:writename, isteğe bağlı topic, private
GET conversations.listchannels:read—
GET conversations.info · conversations.memberschannels:readchannel
GET conversations.historychannels:historychannel, isteğe bağlı limit (1-200)
GET users.listusers:read—
GET users.infousers:readuser (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/unreadschannels: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/pollschat:write
POST /api/channels/:id/join · …/leavechannels:join
POST /api/channels, PATCH /api/channels/:id, POST /api/channels/:id/memberschannels:write
GET /api/users, GET /api/profiles/:kullanici, GET /api/groupsusers:read
GET /api/files · POST /api/filesfiles:read · files:write
/api/canvases…, /api/lists…docs:read (GET) · docs:write
GET /api/communities…, …/events, POST /api/communities/:id/eventscommunities:read · communities:write
GET /api/feed, GET /api/stories, POST /api/postsfeed:read · feed:write
/api/remindersreminders: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" }
DurumAnlamı
400Geçersiz parametre
401Anahtar yok, geçersiz, süresi dolmuş ya da geri alınmış
403Kapsam yetersiz, uç anahtarlara kapalı ya da sahibinin yetkisi yok
404Kayıt yok ya da erişilemiyor
429Hı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.

OlayNe zaman
messageBotun üyesi olduğu kanala mesaj yazıldığında (botun kendi mesajları hariç)
app_mentionMesajda @bot-adi geçtiğinde
reaction_addedBir mesaja tepki eklendiğinde
member_joined_channelKanala 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.

  1. wss://calisma-alaniniz.ornek.com/ws adresine bağlanın.
  2. İlk ileti olarak {"type": "auth", "token": "xbiom-…"} gönderin.
  3. {"type": "ready", "userId": …} gelince bağlantı hazırdır. Anahtar geçersizse bağlantı 4001 koduyla kapanır.
  4. Bağlantıyı canlı tutmak için 25 saniyede bir düz metin ping gönderin; sunucu pong der.
İleti türüİçerik (payload)
app.eventOlay gövdesinin aynısı
app.commandKomut isteği; yanıtı responseUrl adresine gönderin
app.interactionblock_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.

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ıtEtkisi
{"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:

  1. 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=…
    scope boş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.
  2. Kullanıcı giriş yapar ve izin verirse redirect_uri?code=…&state=… adresine döner. Reddederse error=access_denied gelir. Kod 10 dakika geçerlidir ve tek kullanımlıktır.
  3. Kodu sunucunuzda anahtara çevirin (istemci sırrını tarayıcıya vermeyin):
    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-…"}'
    İstemci kimliğini HTTP Basic ile de gönderebilirsiniz. Yanıt: {"access_token": "xbiomu-…", "token_type": "Bearer", "scope": "chat:write users:read", "user": {…}}. Hatalarda code alanı invalid_client, invalid_grant ya da unsupported_grant_type olur.

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.