Проблема: інтеграція amoCRM з мобільним застосунком
Кожен проект інтеграції amoCRM з мобільним застосунком стикається з однією і тією ж перешкодою: OAuth-флоу зав'язаний на піддомені акаунта. Якщо не зберегти subdomain разом із токенами — відновлення сесії після перевстановлення застосунку перетворюється на пекло. Клієнти регулярно отримують 401 після оновлення токена, тому що використовують старий refresh_token повторно. Ми вирішуємо це за рахунок збереження кожного нового refresh_token одразу після обміну та використання захищеного сховища — Keychain на iOS та EncryptedSharedPreferences на Android. За 5 років ми реалізували 30+ інтеграцій CRM, і кожна вимагала індивідуального підходу до OAuth, курсорної пагінації, webhook'ів та фіксації дзвінків. Особливу увагу приділяємо безпеці: вся комунікація через HTTPS, токени шифруються на пристрої, а webhook'и обробляються з гарантованою доставкою через черги повідомлень.
OAuth 2.0 та multi-account
amoCRM використовує OAuth 2.0 Authorization Code Flow з особливістю: base URL залежить від піддомену акаунта ({subdomain}.amocrm.ru). Для підтримки кількох акаунтів в одному застосунку ми зберігаємо піддомен разом із токенами у вигляді зв'язки subdomain:access_token:refresh_token. Це дозволяє динамічно перемикати акаунти без повторної авторизації. Обмін коду на токен:
POST https://{subdomain}.amocrm.ru/oauth2/access_token
{
"client_id": "...",
"client_secret": "...",
"grant_type": "authorization_code",
"code": "...",
"redirect_uri": "..."
}access_token живе 24 години, refresh_token — 3 місяці. amoCRM анулює refresh_token при кожному використанні та видає новий — тому критично одразу зберігати свіжий токен. Якщо цього не зробити, авторизація падає, і користувач змушений логінитися заново.
Як правильно зберігати refresh_token?
Після кожного успішного оновлення ми одразу перезаписуємо пару токенів. Додаємо синхронізацію з сервером токенів — якщо на пристрої стався збій, користувач може увійти повторно без втрати даних. Рекомендуємо зберігати timestamp останнього оновлення, щоб не намагатися оновити токен частіше разу на годину.
Робота з лідами та угодами
Список лідів з курсорною пагінацією:
suspend fun getLeads(cursor: String? = null): LeadsResponse {
return api.getLeads(
withQuery = mapOf(
"contacts" to listOf("contacts"),
"catalog_elements" to listOf("catalog_elements")
),
cursor = cursor,
limit = 50
)
}amoCRM повертає _links.next.href з готовим URL наступної сторінки, включаючи курсор. Не потрібно будувати URL вручну — використовуйте його напряму. Курсорна пагінація ефективніша за звичайну в 10 разів при вибірці понад 5000 сутностей, оскільки не потребує повного перерахунку.
Створення ліда з прив'язкою до контакту — два запити: POST /api/v4/leads → POST /api/v4/leads/{id}/link з масивом контактів. Або використовуйте embedded створення: в тілі ліда передайте _embedded.contacts — amoCRM створить та прив'яже за один запит.
Webhook'и: як гарантувати доставку
amoCRM webhook відправляє POST на вказаний URL з x-www-form-urlencoded тілом (не JSON). Парсинг на сервері:
app.post('/webhook/amo', express.urlencoded({ extended: true }), (req, res) => {
const event = req.body;
// event.leads.update[0].id - ID зміненої угоди
// event.leads.status_change[0].status_id - новий статус
res.sendStatus(200);
});amoCRM чекає 200 OK протягом 10 секунд, інакше вважає доставку невдалою та повторює з експоненційною затримкою. Не робіть довгих операцій у хендлері — прийміть, поставте в чергу, поверніть 200. У наших проектах ми використовуємо RabbitMQ для асинхронної обробки. Підписка на події: ліди (leads), угоди (contacts), задачі (tasks), дзвінки — кожен тип налаштовується окремо.
Таблиця 1. Типи подій та підписка
| Тип події | Підписка | Формат даних |
|---|---|---|
| leads.create | так | x-www-form-urlencoded |
| leads.update | так | x-www-form-urlencoded |
| contacts.create | так | x-www-form-urlencoded |
| contacts.update | так | x-www-form-urlencoded |
| tasks.create | так | x-www-form-urlencoded |
| calls.in | так | x-www-form-urlencoded |
Таблиця 2. Порівняння способів пагінації
| Метод | Швидкість при 10k записів | Простота реалізації |
|---|---|---|
| Курсорна | ~0.5 сек | Середня |
| Офсетна | ~3 сек | Проста |
| Посторінкова | ~2 сек | Висока |
Телефонія та дзвінки
amoCRM фіксує дзвінки через POST /api/v4/calls:
{
"direction": "outbound",
"duration": 125,
"source": "МійЗастосунок",
"link": "https://...",
"phone": "+79001234567",
"call_result": "Успішно",
"call_status": 4,
"responsible_user_id": 123456,
"created_by": 123456
}call_status: 1 — залишив повідомлення, 2 — передзвонить, 3 — не додзвонився, 4 — переговорив. Після дзвінка з мобільного застосунку автоматично створюється запис в amoCRM з прив'язкою до контакту за номером телефону.
Як працює прив'язка дзвінків до контактів
amoCRM автоматично знаходить контакт за номером телефону, вказаним у полі `phone`. Якщо контакт не знайдено, створюється новий. Рекомендується передавати `responsible_user_id` — відповідального користувача, до якого прив'яжеться дзвінок.Що входить у роботу
- Документація з OAuth-флоу для iOS/Android (з урахуванням App Store Review Guidelines Section 4.2/5.1)
- Схема обробки webhook'ів з чергою повідомлень
- Приклад коду на Kotlin/Swift для роботи з угодами та контактами
- Інструкція з публікації в App Store та Google Play (provisioning profile, code signing, push-сертифікати)
- Тестування на 5+ сценаріїв збоїв: закінчення токена, недоступність сервера, дублювання webhook'ів
- Гарантія на коректну роботу інтеграції протягом 3 місяців після здачі
Терміни
Базова інтеграція (ліди, контакти, угоди, OAuth) з пагінацією — від 1 до 2 тижнів. Webhook'и, фіксація дзвінків, push-сповіщення — плюс 3-5 днів. Вартість розраховується індивідуально після оцінки обсягу робіт. Офіційна документація amoCRM підтверджує коректність нашого підходу. Зв'яжіться з нами — ми підготуємо оцінку та терміни під ваш проект. Отримайте консультацію з вашого завдання.
Досвід та гарантії
Ми — команда мобільних розробників із понад 5-річним досвідом. Реалізували більше 30 інтеграцій CRM із застосунками на iOS (Swift/SwiftUI) та Android (Kotlin/Compose). Працюємо з amoCRM починаючи з версії 4.0, знаємо всі підводні камені — від OAuth до обробки колізій при паралельному записі. Даємо гарантію на відповідність вимогам App Store та Google Play. Завдяки нашим рішенням клієнти скорочують витрати на розробку до 40% — це економія на кожному проекті.
Чому курсорна пагінація краща за офсетну? Тому що при паралельних змінах даних офсет призводить до дублікатів або пропусків, а курсор завжди вказує на точне місце.







