NotusCRM

Geliştiriciler

NotusCRM API ve webhook'lar

Dış sistemlerinizi CRM'e bağlayın: REST API ile kayıtları okuyun ve yazın, webhook'larla fırsat, kişi, şirket ve görev değişikliklerini anında alın.

REST API

  • Anahtarı workspace sahibi ya da yöneticisi Ayarlar → API ve webhook'lar'dan oluşturur. Anahtar yalnızca oluşturulduğu anda gösterilir ve ncrm_live_ ile başlar.
  • İsteklerde Authorization: Bearer <anahtar> başlığını gönderin. Workspace'i anahtar taşır; ayrıca başlık gerekmez.
  • Anahtar, onu oluşturan kişinin yetkisiyle çalışır. Varsayılan olarak salt okunurdur; kayıt oluşturmak ve güncellemek için yazma izni verilir (ücretsiz planda salt okunur).
  • Anahtarla kayıt silinemez; anahtar, bağlantı ve webhook yönetimi, e-posta gönderimi, dışa aktarma ve workspace kapatma da kapalıdır. Her yazma denetim kaydına "API · anahtar adı" olarak düşer.
  • Hatalar application/problem+json biçiminde döner: 400 geçersiz istek, 401 anahtar geçersiz, 403 izin yok, 404 bulunamadı, 409 işlem geçerli değil.

Tüm uçlar ve şemalar OpenAPI belgesinde: https://api.notuscrm.com/openapi/v1.json

İstek örneği
curl https://api.notuscrm.com/api/v1/deals \
  -H "Authorization: Bearer ncrm_live_…"

Webhook'lar

  • Uçları yine Ayarlar → API ve webhook'lar'dan ekleyin: HTTPS adres, abone olunacak olaylar. Gizli imza anahtarı (whsec_) yalnızca oluşturulduğunda ve yenilendiğinde gösterilir.
  • Her olay imzalı bir POST isteğiyle gider. 10 saniye içinde 2xx dönen teslim başarılıdır; diğerleri 1 dk, 5 dk, 30 dk, 2 sa, 6 sa, 12 sa ve 24 sa aralıklarla, toplam 8 kez denenir.
  • Art arda 50 başarısız teslimde uç kendiliğinden kapanır. Teslim günlüğü 30 gün saklanır; teslimleri oradan yeniden gönderebilir, "Test gönder" ile ping olayı yollayabilirsiniz.
  • Aynı olay birden çok kez gelebilir (yeniden deneme): gövdedeki id ile tekrarları ayıklayın. Olayların sırası garanti değildir; createdAt'e bakın.
  • data kaydın alanlarını taşır; silme olaylarında yalnızca id gelir. Aşama değişiminde previousStageId de vardır. İç ağ adreslerine gönderim yapılmaz.

Olaylar

  • deal.created
  • deal.updated
  • deal.stage_changed
  • deal.deleted
  • person.created
  • person.updated
  • person.deleted
  • company.created
  • company.updated
  • company.deleted
  • task.created
  • task.updated
  • task.completed
  • task.deleted
  • custom_record.created
  • custom_record.updated
  • custom_record.deleted
Teslim örneği
POST /your/endpoint
Content-Type: application/json
X-Notus-Event: deal.stage_changed
X-Notus-Delivery: 0199c3a1-…
X-Notus-Signature: t=1790000000,v1=5f2b…

{
  "id": "0199c3a0-…",
  "type": "deal.stage_changed",
  "createdAt": "2026-09-26T09:12:44Z",
  "workspaceId": "01a0c31a-…",
  "data": { "id": "…", "title": "…", "stageId": "…", "previousStageId": "…", "amount": 120000, "currency": "TRY" }
}

İmzayı doğrulama

X-Notus-Signature başlığı t (Unix zaman) ve v1 (HMAC-SHA256) değerlerini taşır. İmza, gizli anahtarla t değeri, bir nokta ve ham gövdenin birleşiminden (t.gövde) hesaplanır. Gövdeyi yeniden biçimlendirmeden doğrulayın ve eski zaman damgalı istekleri reddedin.

Node.js
import crypto from "node:crypto";

// rawBody: the request body exactly as received (do not re-serialize JSON)
export function verify(rawBody, header, secret, toleranceSeconds = 300) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) <= toleranceSeconds;
  return fresh && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}
C#
using System.Security.Cryptography;
using System.Text;

static bool Verify(string rawBody, string header, string secret)
{
    var parts = header.Split(',').Select(p => p.Split('=', 2)).ToDictionary(p => p[0], p => p[1]);
    byte[] hash = HMACSHA256.HashData(Encoding.UTF8.GetBytes(secret), Encoding.UTF8.GetBytes($"{parts["t"]}.{rawBody}"));
    bool fresh = Math.Abs(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - long.Parse(parts["t"])) <= 300;
    return fresh && CryptographicOperations.FixedTimeEquals(
        Encoding.ASCII.GetBytes(Convert.ToHexStringLower(hash)), Encoding.ASCII.GetBytes(parts["v1"]));
}