Проблема: інтеграція 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% — це економія на кожному проекті.
Чому курсорна пагінація краща за офсетну? Тому що при паралельних змінах даних офсет призводить до дублікатів або пропусків, а курсор завжди вказує на точне місце.







