API и вебхуки
Связать Нору с Make, n8n, Albato, Zapier, сайтом или своей программой: читать и создавать людей, компании, сделки, задачи и заметки, получать события на свой адрес.
Быстрый старт
- В кабинете откройте Подключения → API и вебхуки и создайте ключ. Ключ показывается один раз: сохраните его сразу.
- Передавайте ключ в заголовке
Authorization: Bearer <ключ>. - Адрес для всех запросов:
https://noracrm.me/v1.
curl https://noracrm.me/v1/me \
-H "Authorization: Bearer nk_XXXXXXXXXXXXXXXX_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Ответ: название кабинета, имя ключа, открытые разделы, список событий и этапов сделки.
Ключи и права
- Ключи создает и отзывает только основной аккаунт кабинета.
- У ключа два уровня прав: только чтение или чтение и запись, и набор разделов: люди, компании, сделки, счета, задачи, заметки.
- Нора хранит только отпечаток ключа (SHA-256). Потеряли ключ: создайте новый, старый отзовите.
- Отозванный ключ перестает работать сразу. Вебхуки, заведенные этим ключом через
/v1/hooks, удаляются вместе с ним. - Не вставляйте ключ в код страниц сайта: он открывает данные кабинета. Ключ живет только на сервере или в Make, n8n и подобных.
Адреса
| Метод и адрес | Что делает | Права |
|---|---|---|
GET /v1/me | Кабинет, ключ, разделы, события, этапы | любой ключ |
GET /v1/events | Список событий вебхуков | любой ключ |
GET /v1/{раздел} | Список страницами | чтение |
GET /v1/{раздел}/{id} | Одна запись | чтение |
POST /v1/{раздел} | Создать запись | запись |
PATCH /v1/{раздел}/{id} | Изменить поля записи | запись |
POST /v1/deals/{id}/stage | Сменить этап сделки | запись |
POST /v1/invoices | Создать черновик счета | запись |
GET|POST /v1/hooks, DELETE /v1/hooks/{id} | Подписки на события из Zapier, Make, n8n | запись |
Разделы: people (люди), orgs (компании), deals (сделки), invoices (счета), tasks (задачи), notes (заметки). Удаление по API закрыто: удаляйте в кабинете.
Списки, курсор, updated_since
Список отдается по возрастанию времени изменения. Параметры: limit (1..200, по умолчанию 50), updated_since (ISO 8601 или миллисекунды), cursor (значение next_cursor из прошлого ответа).
curl "https://noracrm.me/v1/deals?updated_since=2026-11-01T00:00:00Z&limit=100" \
-H "Authorization: Bearer $NORA_KEY"
{
"data": [
{ "id": "d...", "title": "Монтаж 2 сплит-систем", "p": "p...", "amount": 48000,
"stage": "calc", "created_at": "2026-11-03T09:12:40.120Z",
"updated_at": "2026-11-05T14:02:11.004Z" }
],
"has_more": true,
"next_cursor": "WzE3NjIzNTE..."
}
Пока has_more равно true, запрашивайте следующую страницу с cursor. Для регулярной сверки сохраняйте updated_at последней записи и в следующий раз передавайте его в updated_since: записи с тем же временем придут повторно, сверяйте по id.
Создание и изменение
Тело запроса в JSON с заголовком Content-Type: application/json. Поля проверяются так же, как в формах кабинета; неизвестное поле дает ошибку с перечнем допустимых.
curl -X POST https://noracrm.me/v1/people \
-H "Authorization: Bearer $NORA_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Ирина Волкова","phone":"+7 921 000-00-00","email":"irina@mail.ru","tags":["С сайта"]}'
curl -X POST https://noracrm.me/v1/deals \
-H "Authorization: Bearer $NORA_KEY" -H "Content-Type: application/json" \
-d '{"title":"Монтаж кондиционера","p":"p_ID_ЧЕЛОВЕКА","amount":25000}'
curl -X POST https://noracrm.me/v1/deals/d_ID_СДЕЛКИ/stage \
-H "Authorization: Bearer $NORA_KEY" -H "Content-Type: application/json" \
-d '{"stage":"agree"}'
curl -X PATCH https://noracrm.me/v1/tasks/t_ID_ЗАДАЧИ \
-H "Authorization: Bearer $NORA_KEY" -H "Content-Type: application/json" \
-d '{"done":true}'
Ответ на создание: 201 и запись целиком, на изменение: 200 и запись. Смена этапа попадает в ленту сделки, как из кабинета.
Поля
| Раздел | Поля для записи |
|---|---|
people | name (до 80), phone, email, org (id компании), role, ch (tg, wa, max, phone, mail), tags (список), source, city, comment |
orgs | name (до 120), full, inn (10 или 12 цифр), kpp, ogrn, kind, city, address, director, phone, email, site |
deals | title (до 120), p (id человека), org, amount, stage, resp_u, source, comment |
tasks | text (до 300), p, deal_id, due_date (ГГГГ-ММ-ДД), done, resp_u |
notes | text (до 4000), p, deal_id |
Жирным выделены обязательные при создании. Этапы сделки: new новая, calc расчет, agree согласование, work в работе, act акт, paid оплачено. Ответственный resp_u принимается, только если он есть в команде кабинета.
Счета
Счета читаются как другие разделы. Создать можно только черновик: номер, НДС и срок оплаты Нора ставит сама, выставляет и отправляет счет человек в кабинете.
curl -X POST https://noracrm.me/v1/invoices \
-H "Authorization: Bearer $NORA_KEY" -H "Content-Type: application/json" \
-d '{"p":"p_ID_ЧЕЛОВЕКА","items":[{"name":"Монтаж","qty":1,"price":25000}],"due_days":5}'
Поля: p или deal_id (тогда клиент и позиции берутся из сделки), items, what, comment, due_iso или due_days, currency, fx_rate. Статус счета (st): draft, wait, late, paid, cancelled.
Ошибки и лимиты
Ошибка всегда приходит словами в поле text и кодом в поле error:
{ "error": "bad_field", "field": "email", "text": "Почта указана неверно" }
| Код ответа | Когда |
|---|---|
400 | Поле не прошло проверку, неизвестное поле, неверный курсор |
401 | Нет ключа, ключ неверный или отозван |
402 | Бесплатный тариф или кабинет только для чтения |
403 | Ключ только для чтения или раздел ключу не открыт |
404 | Нет записи или адреса |
405 | Метод закрыт (например, удаление) |
429 | Больше 60 запросов в минуту на ключ |
В каждом ответе заголовки X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (секунд до нового окна). При 429 есть Retry-After.
Вебхуки
Нора отправляет POST на ваш адрес, когда в кабинете что-то случилось, откуда бы ни пришло изменение: из кабинета, с формы на сайте, из банка, по API. Адрес задается в Подключения → API и вебхуки: только https://, внутренние адреса и нестандартные порты закрыты.
| Событие | Когда | data |
|---|---|---|
deal.created | Новая сделка | сделка |
deal.stage_changed | Сделка перешла на другой этап. Прошлый этап в previous.stage | сделка |
invoice.paid | Счет отмечен оплаченным (вручную или по выписке банка) | счет |
lead.created | Новая заявка с формы на сайте | заявка: имя, телефон, почта, сообщение, метки, person_id, deal_id |
person.created | Новый человек | человек |
task.done | Задача отмечена выполненной | задача |
ping | Кнопка «Проверить» в кабинете | служебное |
POST /ваш-адрес HTTP/1.1
Content-Type: application/json; charset=utf-8
User-Agent: Nora-Webhooks/1.0 (+https://noracrm.me/developers)
X-Nora-Event: deal.stage_changed
X-Nora-Delivery: ev... (id события, одинаковый во всех повторах)
X-Nora-Attempt: 1
X-Nora-Signature: t=1762351200,v1=5f2b...e9
{
"id": "ev...",
"event": "deal.stage_changed",
"created_at": "2026-11-05T14:02:11.004Z",
"data": { "id": "d...", "title": "Монтаж", "stage": "work", "amount": 48000, "p": "p..." },
"previous": { "stage": "agree" }
}
Ответ и повторы
- Доставка засчитывается при ответе 2xx за 10 секунд. Перенаправления не выполняются: укажите конечный адрес.
- Иначе Нора повторит с нарастающей паузой: примерно через 5 минут, 30 минут, 2, 6, 12 и 24 часа (всего до 7 попыток). Повторы отправляются при ежечасном проходе кабинета, поэтому короткие паузы округляются до часа.
- После 10 неудач подряд адрес выключается, во «Входящие» и в Telegram приходит уведомление. Включается снова кнопкой.
- Одно событие может прийти дважды: проверяйте
X-Nora-Deliveryи не обрабатывайте повтор. - Журнал последних 50 доставок виден в кабинете.
Проверка подписи
У каждого адреса свой секрет подписи (whsec_...), он показывается один раз при создании. Подпись: HMAC-SHA256 секрета от строки <t>.<тело запроса>, в шестнадцатеричном виде. Сверяйте с телом как оно пришло, до разбора JSON, и отклоняйте события старше 5 минут.
// Node.js 18+
import { createHmac, timingSafeEqual } from "node:crypto";
function noraOk(secret, rawBody, header) {
const m = /^t=(\d+),v1=([0-9a-f]{64})$/.exec(header || "");
if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;
const want = createHmac("sha256", secret).update(m[1] + "." + rawBody).digest("hex");
return timingSafeEqual(Buffer.from(want), Buffer.from(m[2]));
}
# Python 3
import hmac, hashlib, re, time
def nora_ok(secret: str, raw_body: bytes, header: str) -> bool:
m = re.fullmatch(r"t=(\d+),v1=([0-9a-f]{64})", header or "")
if not m or abs(time.time() - int(m[1])) > 300:
return False
want = hmac.new(secret.encode(), m[1].encode() + b"." + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(want, m[2])
<?php // PHP 7.4+
function nora_ok(string $secret, string $rawBody, string $header): bool {
if (!preg_match('/^t=(\d+),v1=([0-9a-f]{64})$/', $header, $m)) return false;
if (abs(time() - (int)$m[1]) > 300) return false;
return hash_equals(hash_hmac('sha256', $m[1] . '.' . $rawBody, $secret), $m[2]);
}
Подписка из Zapier, Make, n8n
Сервисы, которые сами заводят адрес для события (REST Hooks), используют ключ с правом записи:
curl -X POST https://noracrm.me/v1/hooks \
-H "Authorization: Bearer $NORA_KEY" -H "Content-Type: application/json" \
-d '{"target_url":"https://hooks.zapier.com/hooks/standard/...","event":"deal.created"}'
curl -X DELETE https://noracrm.me/v1/hooks/wh_ID \
-H "Authorization: Bearer $NORA_KEY"
Можно передать url или target_url, одно событие event или список events. Ответ 201 содержит id и secret. Событие доступно, если ключу открыт его раздел: заявки и новые люди требуют раздел «Люди», события сделок раздел «Сделки».
Make, n8n, Albato, Zapier
- Make: модуль HTTP «Make a request», заголовок
Authorizationсо значениемBearer <ключ>. Для событий: модуль Webhooks «Custom webhook», его адрес вставьте в Норе. - n8n: узел HTTP Request, аутентификация Header Auth (имя
Authorization, значениеBearer <ключ>). Для событий: узел Webhook с методом POST. - Albato: приложение «HTTP Request/Outgoing webhook», действие «Send request» с тем же заголовком; для событий приложение Webhooks (входящий вебхук).
- Zapier: Webhooks by Zapier, действие Custom Request; для событий триггер Catch Hook.
Вопросы и пожелания к API: support@noracrm.me.