01The sheet gate
Everything upstream of the CRM is research, and research is where the mistakes are. So I made the sheet the automation writes into deliberately separate from the sheet that feeds Bitrix. A person reads the rows there, corrects what is wrong, and moves across only what passes. Crossing that line is the instruction: arrival in the connected sheet creates the deal and its contact card, without anyone opening the CRM to type it in. What reaches the pipeline is a prospect somebody has agreed to.
02On the card
The review surface is not a separate tool with a link back to the CRM. I built it as a Bitrix local application, registered to the portal and rendered in place on the record, so the draft is read beside the prospect it was written about. A reviewer opens a deal and the email is there. The sheet is the facts: are the details right. The card is the words: is this the email we want this prospect to receive. Everything between them runs without anyone watching it.
03The five minutes
Approval does not send. Five minutes pass first, and the delay is the point. It keeps the decision and the irreversible act apart rather than letting the same click do both, and I put it there precisely because the rest of the path is fast enough to leave no other place to stand. A window for someone who approved and then thought again. The quietest checkpoint, and the cheapest one to keep.
04After the send
A first email is not the end of anything. The deal moves itself to the next stage as the message goes, and the work that has to happen afterwards is raised as tasks for the people who have to do it. Neither is a button someone remembers to press; both are consequences of the send. The system does not only send, it hands back.
05Undocumented behaviour
Bitrix's REST API is documented in outline and undocumented where it matters, and I have spent a long time at that edge. A greater-than-or-equal filter on the update timestamp is accepted and then quietly ignored, so a query that reads like it is narrowing returns everything. A boolean field written as a number stores the negative of what was intended, without complaining. Records that share a timestamp cannot be told apart by it at all. I established each of those by running against a real portal and reading what came back, because the alternative is building on an assumption that fails silently.