AI integration in amoCRM for auto-replies and lead analysis
A new lead in amoCRM sends a webhook to your server, the model assesses the request, and a hint for the manager appears as a note on the card.
4 min · · бизнес · автоматизация
Managers in amoCRM spend a noticeable part of the day reading new requests, judging their urgency, and deciding what to do next. An AI model can do the first pass for them: amoCRM tells your server about a new lead, the server sends its description to a model via Zukko, and the answer appears as a note on the card. Below are the webhook setup, an API token, a working PHP handler, and a cost estimate.
How the amoCRM AI integration works
- A lead is created in amoCRM → a webhook sends its data to your URL.
- The handler builds the text for analysis from the lead fields.
- The text goes to the model via
https://api.zukko.pro/v1/chat/completions. - The answer is written to the lead as a note through the amoCRM REST API (
/api/v4/leads/notes).
In amoCRM, deals and leads are the same entity — leads in the API and webhooks.
Step 1: a webhook in amoCRM
According to the amoCRM docs (its international version is Kommo, which shares the API), webhooks are set up like this:
- Open Settings → Integrations and click Web hooks in the upper right corner.
- Enter the handler URL, for example
https://your-server.com/amo-handler.php?key=long_random_string. - Select the "Lead added" event and save.
Two details shape the code:
- Data arrives not as JSON but as a regular form (
application/x-www-form-urlencoded):leads[add][0][id],leads[add][0][name],leads[add][0][custom_fields][...]. PHP has already parsed it into$_POST. - amoCRM waits about 2 seconds for a response. If the handler is too slow or returns an error, the webhook counts as undelivered. So we answer
200first and call the model afterwards.
CRM webhooks aren't signed, so add a secret key parameter to the URL and check it in the handler — otherwise anyone could send requests to your URL and spend your balance.
Step 2: a token for the amoCRM API
To write notes, the handler needs access to the account API. For an integration that only runs in your own account, a long-lived token is the simplest option:
- In Integrations, create your own (external) integration.
- On the keys and scopes tab, generate a long-lived token and choose its expiry.
- Store it in a server environment variable.
The token works with the rights of the administrator who created it, so treat it like a password. Exact button names depend on the interface version — check the amoCRM developer docs. If the integration will be installed in other people's accounts, you need full OAuth authorization with token refresh.
Step 3: a PHP handler
<?php
// amo-handler.php — amoCRM "Lead added" webhook handler
if (!hash_equals((string) getenv('AMO_HOOK_KEY'), (string) ($_GET['key'] ?? ''))) {
http_response_code(403);
exit;
}
// amoCRM waits no more than ~2 seconds: respond right away (PHP-FPM)
http_response_code(200);
echo 'OK';
if (function_exists('fastcgi_finish_request')) {
fastcgi_finish_request();
}Environment variables: ZUKKO_API_KEY, AMO_SUBDOMAIN, AMO_TOKEN, and AMO_HOOK_KEY (the secret string from the webhook URL). Replace the field names in ALLOWED_FIELDS with your own: this way only data needed for the assessment goes to the model, without customer contacts. For a Kommo account, the API host is your_account.kommo.com.
If PHP doesn't run under FPM and fastcgi_finish_request isn't available, save incoming events to a database or file and process them with a separate cron script.
A task instead of a note
For urgent leads it's handier to create a task for the responsible user right away. That's the POST /api/v4/tasks method:
function addTask(int $leadId, string $text): void
{
$subdomain = getenv('AMO_SUBDOMAIN');
$ch = curl_init("https://{$subdomain}.amocrm.ru/api/v4/tasks");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([[
'entity_id' => $leadId,
'entity_type' => 'leads',
'text' => $text,
'complete_till' => time() + 3600, // due in one hour
]], JSON_UNESCAPED_UNICODE),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('AMO_TOKEN'),
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
]);
curl_exec($ch);
}To decide when to create a task, ask the model to start its answer with "HIGH", "MEDIUM", or "LOW" and check the first word in code.
What it costs
Example: 50 leads a day, about 300 input and 100 output tokens each. Per day that's 50 × 400 = 20,000 tokens, or 0.02M.
| Model | Price in/out per 1M | Per day | Per 30 days |
|---|---|---|---|
glm-5.3-flash | $0.04 / $0.04 | 0.02 × 0.04 = $0.0008 | $0.024 |
gpt-5.6-luna | $0.1 / $0.1 | 0.02 × 0.1 = $0.002 | $0.06 |
claude-sonnet-5 | $0.3 / $0.3 | 0.02 × 0.3 = $0.006 | $0.18 |
At 500 leads a day, multiply by 10: on glm-5.3-flash that's $0.24 per 30 days. Real token counts are in the response's usage field and in the spending history in the dashboard. How useful a model is for your particular requests is something to test on a sample: run 30–50 past leads with a known outcome through two or three models and compare. Request parameters are in the Chat Completions docs.
Personal data
Customer data ends up in the model request, so:
- Send only the fields needed for the assessment (the
ALLOWED_FIELDSlist in the code). Phone, email, and full name aren't needed to judge urgency. - Don't write full lead data to logs — the ID and error code are enough.
- Make sure processing data with an external service doesn't conflict with your policy and your customers' consents.
FAQ
The webhook doesn't arrive — what should I check?
- The webhook is saved and the right event is selected.
- The URL is reachable from the internet over HTTPS.
- The handler responds with
200in under 2 seconds. For debugging, temporarily log incoming data to a file:file_put_contents('/tmp/amo.log', print_r($_POST, true), FILE_APPEND);
How do I check that the token works?
Request the list of leads:
curl -H "Authorization: Bearer YOUR_TOKEN" \
"https://your_account.amocrm.ru/api/v4/leads?limit=1"A response with data means the token is valid; 401 means it's wrong or expired.
Notes aren't being added — why?
Check error_log: amoCRM returns an error code and description. Common causes are a wrong subdomain, an expired token, or a lead ID the token owner can't access.
Where do I get a Zukko key, and how do I cap spending?
Create a separate key for amoCRM in the dashboard, set a daily limit, and allow only the model you need — then an accidental loop in the handler can't overspend. More in the key limits section.
zukko
Pay 25×
less
for Claude Code & ChatGPT
One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.
Related articles
- AI for testers: test cases, checklists and bug reportsHow a QA engineer can use a model for test cases, checklists and bug reports, check coverage, and avoid requirements the model made up.
- Anonymizing data before sending it to a neural network: a practical wayYou do not have to send personal data to a model for it to process a document. How to replace it with labels, restore it in the answer and check that nothing leaked.
- A neural network for HR: job posts, candidate emails and resume reviewA model can draft job posts and emails and do a first-pass resume review. What to hand over, how to treat candidates' personal data and how to prevent biased decisions.
- Generating an FAQ with a neural network from tickets and a knowledge baseA good FAQ is built on what customers really ask. A pipeline: group the tickets, answer from the knowledge base with a source reference, and verify the result.