# OneSwitch — full site text Websites, web apps, Telegram bots and Mini Apps, integrations, scraping, 1C and AI agents. Systems that keep working without supervision. # Services ## Website and landing page development URL: https://oneswitch.ru/en/uslugi/sajty-i-lendingi/ I build sites that load fast, look good on a phone and are ready for promotion from day one: structure, markup, sitemap and files for AI. Includes: Design and responsive layout; Lead forms to email, Telegram or CRM; SEO basics: tags, structured data, sitemap, robots; AI optimization: llms.txt and structured data; Analytics and goals; Deployment to your hosting or VPS For: Businesses that need a business card site or an ad landing page; Experts and studios with a portfolio; Projects that need a site generated from data Result: A working site you can show to clients and promote right away, with the source code in your hands. Price: from $250. Term: 5–14 days. Stack: HTML/CSS/JS, Python generators, Next.js, Tailwind, CMS. Q: Why is a static site better than a site builder? A: It is faster, cheaper to host, indexes better and does not depend on a platform's pricing. Content can be managed through an API or files. Q: How long does a landing page take? A: Usually 5–7 days if texts and materials are ready. ## Web application and client account development URL: https://oneswitch.ru/en/uslugi/veb-prilozheniya/ I design and build services with authentication, a database and an API: from an internal admin panel to a customer portal. Includes: Data and API design; Authentication and roles; Admin panel for content management; Calculators, catalogs and filters; Notifications to Telegram and email; Integrations with external services For: Companies moving a process from spreadsheets into a service; Startups that need an MVP; Projects with a catalog and filters Result: A working service with a clear admin panel and API documentation. Price: from $850. Term: 3–6 weeks. Stack: Python, aiohttp / FastAPI, PostgreSQL / SQLite, JavaScript, Docker. Q: Can we start with an MVP? A: Yes. I pick the main scenario, launch it quickly and grow it based on real usage. ## Service integrations and API development URL: https://oneswitch.ru/en/uslugi/integracii-i-api/ I connect your site, CRM, payment systems, messengers and accounting systems so data moves by itself instead of by hand. Includes: REST APIs and webhooks; Exchange with CRM, 1C and spreadsheets; Partner APIs (for example Travelpayouts); Queues, retries on failure, logs; Method documentation For: Teams that move data between services manually; Projects with affiliate programs; Teams that need an API for their own apps Result: An integration that runs on a schedule or on an event and reports errors. Price: from $125. Term: 2–10 days. Stack: REST, Webhooks, n8n / Make, Python, PostgreSQL. Q: What if a service has no API? A: Then I look for an alternative: exports, webhooks or browser automation. I choose the most stable path. ## Business process and routine automation URL: https://oneswitch.ru/en/uslugi/avtomatizaciya-processov/ I find repetitive actions and turn them into scenarios that run on a schedule or on an event, with logs and notifications. Includes: Process audit and choosing what to automate; Scenarios in n8n and Make or custom scripts; Scheduled reports and exports; Result control: logs, checks, notifications; Handover of scenarios and instructions For: Managers and marketers with a lot of routine; Small teams without their own developer; Projects with regular publishing and mailings Result: Less manual work, predictable results and clear logs. Price: from $125 per scenario. Term: 2–10 days. Stack: n8n, Make, Python, Node.js, cron, PostgreSQL. Q: n8n or a custom script? A: For typical integrations n8n is visual and easy to change. For complex logic and high volumes code is more reliable. I choose by the task. Q: How will I know a scenario broke? A: I add result checks and Telegram notifications, so you find out immediately. ## Telegram bot and Mini App development URL: https://oneswitch.ru/en/uslugi/telegram-boty-i-mini-app/ I build bots and apps inside Telegram: catalogs with filters, subscriptions to new offers, notifications, lead capture and AI assistants. Includes: A bot with a menu, commands and scenarios; A Telegram Mini App with a catalog, filters and cards; Subscriptions to notifications by criteria; Admin tools and manual control when needed; Auto-posting to channels and groups by topic; Connection to your site and database For: Catalog projects: real estate, tickets, services; Businesses that need leads straight from a messenger; Channels and groups that need auto-posting Result: A bot or Mini App that opens in one tap and works around the clock. Price: from $185. Term: 3–21 days. Stack: Telegram Bot API, Mini App, Python, aiohttp, PostgreSQL, n8n. Q: Why a Mini App if I have a site? A: It opens inside Telegram without leaving or logging in, supports notifications and is comfortable on a phone. The site stays for search and SEO. Q: Can users subscribe to new listings? A: Yes. A user saves criteria and gets a message when a matching option appears. ## Web scraping and data work URL: https://oneswitch.ru/en/uslugi/parsing-i-dannye/ I collect data from open sources and APIs, bring it to one format and put it where it is convenient: a database, a spreadsheet or a catalog. Includes: Collection from APIs and public pages; Cleaning and deduplication; Storage in PostgreSQL or SQLite; Spreadsheet exports and reports; Change and price monitoring For: Aggregators and catalogs; Marketers and analysts; Projects with price monitoring Result: An up-to-date database and regular exports without manual copying. Price: from $125. Term: 3–10 days. Stack: Python, Playwright, PostgreSQL, SQLite, n8n. Q: Is it legal? A: I work only with open data and APIs, following the sources' rules and request rate limits. ## Content and social media publishing automation URL: https://oneswitch.ru/en/uslugi/kontent-i-soczseti/ I build pipelines: data turns into articles, cards and videos that are published on schedule, with a check that each post really went out. Includes: Generating pages and articles from structured data; Photo selection and video rendering; Publishing to Telegram, Instagram, TikTok, Pinterest, YouTube and Dzen; Schedule, queue and retry on failure; Verification that the publication is live For: Information portals and blogs; Channels with a large stream of offers; Owners with no time for manual posting Result: Regular content without manual routine and with quality control. Price: from $300. Term: 1–3 weeks. Stack: Python, Playwright, ffmpeg, n8n, PostgreSQL. Q: Will platforms ban auto-posting? A: Every platform has its own rules. I use official APIs where they exist and careful scenarios with pauses where they do not. I discuss risks in advance. ## 1C development and customization URL: https://oneswitch.ru/en/uslugi/1c/ I write external processing and reports, configuration extensions, forms and print forms, and set up data exchange with your site and other services. Includes: External processing and reports (EPF/ERF); Configuration extensions (CFE); Managed forms and data composition schemas; Layouts and print forms; Roles and subsystems; Exchange with sites and messengers, HTML forms inside the client; Form autotests with Vanessa Automation For: Companies on 1C that need customization without touching the standard configuration; Teams that need exchange between 1C and a website; Anyone who wants to automate exports and reports Result: Customization in an extension instead of editing the standard configuration, plus tests and documentation. Price: from $30/hour. Term: by estimate. Stack: 1C:Enterprise, XML sources, Git, Vanessa Automation. Q: Do you work with standard configurations? A: Yes, I prefer extensions: updating the standard configuration does not break the customization. Q: Are there ready-made solutions? A: Yes. The extension “Local document recognition from photos for 1C” is sold on Infostart: it fills UPD and TORG-12 from photos and PDFs without internet. Q: Can I connect AI to 1C without sending data outside? A: Yes. The model runs locally on the client's computer (LM Studio), so documents and prices never reach third-party servers. ## AI agent and LLM automation development URL: https://oneswitch.ru/en/uslugi/ai-agenty/ I build assistants that use your data and APIs: they search tickets, answer customers, classify requests and subscribe users to alerts. Includes: An agent with tools (search, subscribe, API requests); Conversation memory; Model connections (OpenRouter, DeepSeek and others); Request classification and routing; Knowledge base search; Limits, logs and guards against wrong answers For: Projects that need a consultant in Telegram or on a site; Support teams with a flow of typical questions; Services where answers must rely on real data Result: An assistant that answers from your data instead of making things up. Price: from $300. Term: 1–3 weeks. Stack: LLM, OpenRouter, DeepSeek, n8n, Python, REST API. Q: How do you avoid made-up answers? A: The agent gets data through tools and APIs, and answers are built from it. I limit the topic and log conversations. ## SEO and optimization for AI answers (GEO) URL: https://oneswitch.ru/en/uslugi/seo-i-ai-optimizaciya/ I prepare your site for search and for AI answers: clean structure, structured data, sitemap, files for AI and content that is easy to quote. Includes: Technical audit and fixes; Schema.org structured data (JSON-LD); sitemap.xml, robots.txt, canonical, Open Graph; llms.txt and machine-readable catalogs; Article structure “short answer first” for citation; Analytics and webmaster tools setup For: Information portals; Projects that want to appear in AI answers; Sites after a redesign Result: A site that both search engines and language models can understand. Price: from $185. Term: 5–10 days. Stack: Schema.org, JSON-LD, llms.txt, sitemap, Yandex Webmaster, Search Console. Q: What is GEO? A: Generative Engine Optimization: preparing content so that AI systems can find, understand and correctly quote it in their answers. Q: Does it guarantee rankings? A: No, nobody can guarantee that in SEO. I improve what depends on the site and show exactly what changed. ## Automated testing of sites and apps URL: https://oneswitch.ru/en/uslugi/avtotesty/ I write scenarios that check critical paths by themselves: forms, payments, 1C forms and publications, and tell you when something breaks. Includes: Playwright scenarios for sites; Checks of forms and leads; 1C form tests with Vanessa Automation; Screenshots on failure; Run on a schedule or before a release For: Projects that change often; Teams afraid to deploy changes; Sites with lead forms and payments Result: Confidence at every release and a quick signal when something breaks. Price: from $100. Term: 2–7 days. Stack: Playwright, Vanessa Automation, CI, Python, JavaScript. Q: Do I need to cover everything with tests? A: No, I start with the most important scenarios where a failure costs the most. ## Deployment, hosting and technical support URL: https://oneswitch.ru/en/uslugi/deploy-i-podderzhka/ I deploy your project to a server, set up the domain, HTTPS, autostart and backups, and then support and improve it after launch. Includes: VPS, nginx, HTTPS; Autostart with systemd and Docker; Backups and recovery; Monitoring and alerts; Improvements and maintenance; Handover of access and documentation For: Projects without their own administrator; Anyone who wants a reliable launch without downtime; Teams that need a developer on retainer Result: The project runs stably, and you learn about problems before your customers do. Price: from $85/month. Term: as agreed. Stack: Linux, nginx, systemd, Docker, Git, Certbot. Q: What does support include? A: Monitoring, updates, backups, small fixes and consultations. Larger improvements are estimated separately. # Work ## InsureHub: an insurance portal URL: https://oneswitch.ru/en/raboty/insurehub/ An information portal on car, mortgage, travel and property insurance. Pages are built by a Python generator. Task: Launch an information portal about insurance that grows fast and is well indexed by search engines and AI. A static site that a Python builder assembles from structured data. A new section or article appears in minutes, not days of layout work. Sections: reference, journal, company ratings, insurance directions, partner contracts. A server API accepts forms and leads. For search engines and AI: sitemap, search.json, llms.txt and ai-catalog.json. Stack: Python, HTML/CSS/JS, REST API, SEO, Schema.org. ## HotTrip: flights, hot tours, a bot and a Mini App URL: https://oneswitch.ru/en/raboty/hottrip/ An ecosystem around flights and tours: a portal, an AI bot, a Telegram Mini App, an API and an automated channel. Task: Build one ecosystem around flights and tours: a site that search engines and AI can find, a consultant bot and a flow of content for channels without manual work. Portal: flight search with a departure city, a feed of hot flights from Telegram, currency rates, a journal of news and reviews, destinations, guides, visas and travel insurance. An AI assistant suggests tickets and subscribes users to price drop alerts. Bot and API: a Telegram bot built on an LLM agent (OpenRouter, DeepSeek) with tools for flight search, popular destinations, price radar subscriptions and detecting the city from geolocation. Data comes from the Travelpayouts API and our own aiohttp REST API. Mini App: a catalog of hot tickets, search, price radar, insurance and a traveler checklist inside Telegram. Affiliate links go through a safe redirect that counts clicks. Content factory: every 2 hours n8n pulls offers, stores them in PostgreSQL, builds city digests, picks Pexels photos, renders video with ffmpeg and publishes to the automated channel. Stack: n8n, PostgreSQL, Telegram Bot API, Telegram Mini App, OpenRouter, DeepSeek, Travelpayouts, ffmpeg, aiohttp. ## Da Nang House: rentals in Vietnam URL: https://oneswitch.ru/en/raboty/danang-house/ A catalog of rental housing in Da Nang with a bot, a Mini App, subscriptions to new listings and auto-posting to a group. Task: Build a catalog of Da Nang housing so newcomers find places by district, type and budget, and new listings appear without manual work. Catalog: filters by district, property type and budget in VND, sorting, favorites, photos and video in the card, a map and a contact button. The database refreshes automatically every 15 seconds. Automation: a listing from the site goes through a webhook into n8n, is saved to PostgreSQL, posted to the chat and updates the catalog. Mini App and subscriptions: the catalog inside Telegram, a listing card with a gallery and map, saved searches and subscriptions to new listings by criteria. Everything runs without an administrator. Group: topics by budget (under 7, 7–10, 10–15 and over 15 million, “Price on request”), auto-posting of listings and a pinned “Open catalog” button. Stack: n8n, PostgreSQL, Telegram Bot API, Telegram Mini App, Webhooks. ## Social media auto-publishing pipeline URL: https://oneswitch.ru/en/raboty/publishing-pipeline/ Site material becomes posts and videos that go to five platforms on schedule, with verification of the result. Task: Publish site materials to social networks without manual work and be sure each post is really live. Platforms: Instagram, TikTok, Pinterest, YouTube and Dzen. Each one has its own publishing scenario. After publishing, scripts check the schedule and the result, and capture errors with a screenshot and a log. On failure the operation is retried and a notification is sent. Stack: Python, Playwright, ffmpeg, n8n. ## Local document recognition from photos for 1C URL: https://oneswitch.ru/en/raboty/raspoznavanie-dokumentov-1c/ A 1C extension: a photo, scan or PDF of an invoice fills the document in 30–60 seconds. Local AI, no internet and no cloud. Task: Accountants and warehouse staff re-type supplier invoices by hand: UPD and TORG-12, line by line. One document takes 10–15 minutes, and there are dozens a day. Cloud OCR services are not an option because documents with prices and tax IDs would go to third-party servers. A 1C extension that uses a local AI model running on the client's computer through the free LM Studio. Data never leaves the company, no internet is needed. How it works: take a photo or scan a document (phone photo, scan, PDF, multi-page), press “Recognize”, review and post. The extension detects the document type, finds the supplier and matches items from the nomenclature catalog. Features: UPD and TORG-12, automatic type detection, JPG, PNG and PDF formats, item matching, supplier lookup. New document types are added as a separate service, and filling rules are tuned to your accounting policy. Tested on 1C:Trade Management 11.5 and 1C:Accounting 3.0; for KA, ERP, UNF and customized configurations a custom integration is done. The source code is open. Sold on Infostart: the extension for UT 11.5 or BP 3.0 with installation and setup for 12,200 ₽ (about $150), a bundle with custom integration for 30,500 ₽ (about $375), a new document type for 3,000 ₽ (about $37), technical support for 3,000 ₽ per month (about $37). Stack: 1C:Enterprise, Configuration extension, Local AI, LM Studio, OCR. ## 1C development tooling URL: https://oneswitch.ru/en/raboty/1c-tools/ A working pipeline for 1C: metadata, building processing, extensions, XML export and form testing. Task: Develop for 1C the way we develop for other systems: with sources in Git, checks and autotests. Creating and validating metadata, forms, layouts, roles, subsystems and data composition schemas. Building external processing and reports, configuration extensions, exporting and loading configurations through XML. Exchange with websites and messengers, HTML forms inside the 1C client and form testing in Vanessa Automation. Stack: 1C:Enterprise, XML, Git, Vanessa Automation. # Pricing - Start (Landing page, business card site, ad page): from $250, 5–7 days - Business (Multi-page site, web app, integrations): from $850, 3–6 weeks - Automation (Bot, Mini App, scraper, script, AI agent): from $125, per scenario, 2–10 days - 1C: processing, reports, extensions: from $30/hour or by estimate - Support: from $85/month: fixes, monitoring, backups - Hourly work: $25/hour for small improvements # Blog ## Telegram Mini App notifications: how to send push messages through the bot URL: https://oneswitch.ru/en/blog/uvedomleniya-v-telegram-mini-app/ Date: 2026-10-30 A Mini App opens inside Telegram, but it **has no push notifications of its own**. Everything a user receives “outside the app” is a message from the bot. Here is how it works and which mistakes get in the way most often. ## How notifications work A Mini App is always tied to a bot. When you need to notify a user (a new item appeared, a price dropped, an order is ready), your server calls the `sendMessage` Bot API method as the bot. The message arrives in the private chat with the bot and Telegram shows an ordinary notification. For the bot to write to a user one of these must be true: - the user **started the bot** (pressed “Start”); - the Mini App **requested permission** to message the user and they agreed. ## How to get permission from a Mini App If a user opened the app through a direct link and never started the bot, you may not be allowed to write to them. The user data in `initData` has an `allows_write_to_pm` flag. If it is not set, ask for permission: ```javascript const tg = window.Telegram.WebApp; if (!tg.initDataUnsafe.user?.allows_write_to_pm) { tg.requestWriteAccess((granted) => { // granted === true: you can send messages }); } ``` The `requestWriteAccess` method is available in Bot API 6.9 and newer. Check support in your users' clients and keep a fallback: an “Enable notifications” button that opens the bot chat. Do not ask for permission on first launch. The best moment is when it makes sense: after the user presses “Subscribe to new listings” or “Tell me about the price”. ## Sending a notification The ID of the private chat with a user equals their `user_id`. The server calls: ```python import requests def notify(token: str, user_id: int, text: str, app_url: str) -> bool: r = requests.post( f"https://api.telegram.org/bot{token}/sendMessage", json={ "chat_id": user_id, "text": text, "reply_markup": {"inline_keyboard": [[ {"text": "Open", "web_app": {"url": app_url}} ]]}, }, timeout=10, ) return r.ok ``` A button with `web_app` opens the app right from the message. Keep the bot token on the server and never give it to the app. ## How to open the right screen To make a notification lead to a specific item there are two ways: 1. **The address in the `web_app` button:** add parameters to the URL (`?item=123`) and the app opens the right card. Do not trust them without server-side checks. 2. **A Mini App direct link** like `https://t.me//?startapp=item_123`. The parameter value is available in the app as `start_param` in `initData`. ## Errors and limits - **The user blocked the bot.** Telegram returns an error (code 403). Mark that user as unsubscribed and do not try again. - **Limits.** Do not send messages too often: Telegram has rate limits. For mass mailings use a queue and pauses. - **Duplicates.** Store what has already been sent to each user so a worker restart does not repeat messages. More on duplicate protection: [how not to publish repeats](/blog/dedup-v-avtoposting-n8n-postgresql/). - **Frequency.** Combine events into one digest instead of a message per event. - **Silent messages.** For unimportant events use `disable_notification` so the message arrives without a sound. - **Consent.** Give an easy way to turn notifications off right in the message or the app. ## Where this is applied This is how subscriptions work in our projects: a user saves criteria in the Mini App and the bot sends a notification when a matching option appears. More in the breakdown of [catalog architecture](/blog/katalog-v-telegram-mini-app-arhitektura/) and in the projects [Da Nang House](/raboty/danang-house/) and [HotTrip](/raboty/hottrip/). Service: [Telegram bots and Mini Apps](/uslugi/telegram-boty-i-mini-app/). ## FAQ ### Can a Mini App send a push by itself, without a bot? No. Notifications are sent by the bot the app is attached to. ### Does the user have to press Start to get messages? Either they start the bot or they grant permission to message them through `requestWriteAccess`. Without that the bot cannot write first. ### How do I tell that a user blocked the bot? By the error on sending: Telegram returns a refusal with code 403. After that stop messaging them and mark the subscription inactive. ### How do I pass data from a notification into the app? Through the URL parameters of the `web_app` button or the `startapp` parameter of a direct link. On the server always check that the user may see that data. ## A Telegram bot in n8n: inline buttons, menus and a Mini App button URL: https://oneswitch.ru/en/blog/telegram-bot-n8n-knopki-menu-mini-app/ Date: 2026-10-30 In n8n you can build a bot without separate code: receiving messages, a menu, buttons and replies. Here is the workflow layout, button handling and a button that opens a Mini App. ## What a bot in n8n consists of 1. **Telegram Trigger**: receives updates (messages and button presses). 2. **A branch (Switch or IF)**: decides what arrived: a command, text or a button press. 3. **Processing nodes:** database queries, APIs, calculations. 4. **A Telegram send node** or **HTTP Request**: sends the reply to the user. For the trigger to work permanently the workflow must be **activated**: test mode is only for checking, and the production webhook is registered on activation. n8n needs a public HTTPS address for that. ## Commands and menu Commands like `/start` arrive as ordinary messages, so check the beginning of the text in your branch. Command hints in the Telegram interface are set in **@BotFather** (the `/setcommands` command): that is just a list for the user, your workflow handles the logic. ## Inline buttons Inline buttons are sent in the message node through the keyboard setting (Reply Markup, Inline Keyboard). Each button has text and either `callback_data` or a link. When a user presses a button with `callback_data`, Telegram sends a **callback_query** update, not a message. It contains the button data and a query identifier. Important rules: - **Answer the press.** You must call the answer to the callback query (in the Telegram node this is the Answer Query operation), otherwise the user sees a loading spinner on the button. - **Parse `callback_data`** with a branch: for example `catalog:next`, `sub:on`, `sub:off`. Keep the values short: Telegram limits their length. - **Edit the original message** instead of sending a new one when it is a page or state switch. That keeps the chat clean. ## A button that opens a Mini App The easiest way to send a button that opens a Mini App is the **HTTP Request** node, calling the Bot API directly. The address is `https://api.telegram.org/bot/sendMessage`, with a JSON body: ```json { "chat_id": "{{ $json.message.chat.id }}", "text": "Open the catalog", "reply_markup": { "inline_keyboard": [[ { "text": "Catalog", "web_app": { "url": "https://example.com/app" } } ]] } } ``` The Mini App address must be reachable over HTTPS. Keep the bot token in n8n credentials, not in the node text. ## Pitfalls - **One webhook per bot.** A bot can have only one active webhook. If you run a Telegram Trigger in n8n and also poll `getUpdates` from code or register another webhook, you get conflicts and lost messages. - **Test and production addresses.** In test mode the webhook has a different address. Do not leave a test URL on the bot. - **Repeated messages.** Telegram retries delivery if it did not get a quick reply. Avoid long operations before replying and protect critical actions from repeats (remember the `update_id`). - **Sending limits.** Do not send many messages in a row: use pauses and a queue. - **User-facing errors.** If a database query fails, send a clear message instead of leaving the bot silent. ## Where this is used n8n runs, for example, the HotTrip AI consultant: n8n receives messages, calls tools and APIs, and replies arrive in Telegram. In projects with a Mini App the bot's buttons lead into the app. Details are in the [HotTrip](/raboty/hottrip/) and [Da Nang House](/raboty/danang-house/) projects and in [Telegram bots and Mini Apps](/uslugi/telegram-boty-i-mini-app/) and [Process automation](/uslugi/avtomatizaciya-processov/). ## FAQ ### Do I need code to build a bot in n8n? For a typical bot, no: the menu, buttons, replies and API requests are built from nodes. You need code for non-standard logic or features the Telegram node does not have. ### Why does a button “hang” after a press? The answer to the callback query was not sent. Add the answer operation to your workflow. ### Can I build a bot and a Mini App together? Yes. The bot sends a button with `web_app`, the Mini App opens inside Telegram and calls your API. User data must be verified by the `initData` signature. ### What if the bot stopped receiving messages? Check that the workflow is activated, that the bot has the right webhook set and that no other process uses the same token. ## How much a Telegram bot and Mini App cost: what the price is made of URL: https://oneswitch.ru/en/blog/skolko-stoit-telegram-bot-i-mini-app/ Date: 2026-10-30 The honest answer to “how much does a bot cost” runs from “cheap” to “like a small web app”. Below are the project types, price factors and the reference points I use in my work. ## Three project types | Type | What it does | Reference | |---|---|---| | **A simple bot** | Menu, replies, leads sent to a chat or a spreadsheet | from $185 (15,000 ₽), from 3 days | | **A bot with integrations and AI** | Data from CRM, 1C or an API, subscriptions, notifications, an AI consultant | more than a simple bot, depends on integrations, 1–3 weeks | | **A Mini App** | An interface inside Telegram: catalog, filters, cards, a personal account | close to the Business package (from $850), usually 3–6 weeks | These are my “from” reference points, not fixed prices: I name the exact cost after a short brief and fix it before work starts. Full prices are in the [Pricing](/ceny/) section. ## What affects the cost - **Number of scenarios.** One “leave a request” scenario and fifteen branches with conditions are different scopes. - **Integrations.** CRM, payments, 1C and affiliate APIs: every link adds work and tests. - **Data and database.** If you need to store users, subscriptions and history, a database and API must be designed. - **Interface.** A bot uses ready-made Telegram elements, while a Mini App is a custom interface that must be designed and built. - **AI.** An assistant with access to your data needs tools, checks and limits set up. - **Roles and admin panel.** A separate panel for content or leads is an extra part of the project. - **Reliability.** Logs, retries, error notifications and autotests raise the price but lower the risk of failures. - **Deadlines.** Urgent work usually costs more. ## What is not included in the development price These costs are paid separately and do not depend on the developer: - a server or hosting and a domain; - paid external APIs and subscriptions; - AI model tokens, if cloud models are used. I state their size in advance so there are no surprises. ## How to save without losing quality 1. **Start with a minimal version.** Launch the main scenario and develop it based on real data. 2. **Describe the task in your own words:** what should happen, for whom and what counts as success. 3. **Use ready-made Telegram elements** where a custom interface is not needed. 4. **Agree on stages and payment by results.** 5. **Ask for the source code and access right away.** ## A bot or a Mini App If you need short scenarios (a lead, a notification, an answer to a question), a bot is enough. If you need a catalog with filters, photos and a personal account, a Mini App is much more convenient, and the bot remains the notification channel. More in the comparison [Mini App or a website](/blog/telegram-mini-app-ili-sajt/) and in the article on [catalog architecture](/blog/katalog-v-telegram-mini-app-arhitektura/). ## Examples A bot and a Mini App with subscriptions and a catalog: [Da Nang House](/raboty/danang-house/). A bot with an AI consultant, a Mini App and an automated channel: [HotTrip](/raboty/hottrip/). The service: [Telegram bots and Mini Apps](/uslugi/telegram-boty-i-mini-app/). ## FAQ ### Can I build a bot for free or very cheaply? A simple bot can be assembled yourself with a builder. But once you need integrations, a database or non-standard logic, you need development. ### How long does development take? A simple bot takes a few days, a bot with integrations 1–3 weeks, a Mini App 3–6 weeks. Timelines depend on scope and how quickly approvals go. ### What should I prepare to get an exact estimate? A scenario description, a list of integrations and data, examples of similar solutions and a desired deadline. A few lines are enough, the rest we clarify at the brief. ### Do I need support after launch? It is advisable: updates, monitoring and small improvements. Support is priced separately, usually monthly. ## Invoice recognition in 1C from photo and PDF: cloud or local AI URL: https://oneswitch.ru/en/blog/raspoznavanie-upd-v-1s-chem-zagruzit-dokumenty/ Date: 2026-10-30 A supplier invoice can get into 1C in four ways. Each has its own conditions and there is no universal winner. Below are a comparison, a testing checklist and the errors recognition makes most often. ## Four ways to enter a document | Method | When it fits | What to consider | |---|---|---| | **Manual entry** | A few documents a month | Slow: 10–15 minutes per document, easy to make mistakes in lines | | **From EDI (XML)** | The supplier sends an electronic UPD | The most accurate way: no recognition needed, data arrives as a structure | | **Cloud OCR** | Paper documents, no restrictions on sending data | Documents with prices and tax IDs go to third-party servers, internet required | | **Local AI model** | Paper or scanned documents, data must not leave the company | Needs a computer with enough power, result depends on the model and scan quality | The main rule: **if a document arrives electronically through EDI, there is nothing to recognize**. Recognition is for paper, scans and photos, where there is no data structure. ## When you need a local neural network A local setup is chosen in three cases: 1. **Data must not leave the company.** Invoices contain purchase prices, tax IDs and supplier lists. For some companies this is a trade secret or a security requirement. 2. **There is no stable internet** or it is restricted by company policy. 3. **You need control over filling rules:** how items are matched and which accounting policy applies. If none of these apply, a cloud service is simpler: no computer or model to set up. ## What local mode requires - A program to run the model, for example **LM Studio**: free, runs on the user's computer. - A model that can read images (a vision model). - A computer with enough power. A model can run on a CPU too, but on weak hardware a document takes noticeably longer. Rely on a test on your own computer, not on other people's numbers. - A 1C extension that sends the image to the model and fills the document. ## How to test any solution on your documents Do not trust demos, test on your data: 1. Take **20–30 real documents** of different quality: clean PDFs, scans, phone photos, crumpled ones, multi-page ones. 2. For each, compare: **supplier and tax ID, numbers and dates, quantities and prices per line, VAT and the total**. 3. Look separately at item matching: how many items matched by themselves and how many needed manual fixes. 4. Measure time: from pressing the button to a filled document. 5. Check what happens to what was not recognized: it should be clearly marked, not a silent error. The readiness criterion is simple: the document total in 1C equals the paper total, and human review takes less time than manual entry. ## Where recognition fails most often - **Similar characters:** 0 and O, 1 and I, 5 and S in article numbers and tax IDs. - **Merged or shifted columns** in narrow tables. - **Stamps and signatures** covering digits. - **Multi-page documents** where the header and the total are on different pages. - **Angled photos** and poor lighting. - **Units of measure** (pcs, pack, kg) that do not match the catalog. That is why such documents cannot be posted without review. The right scheme: the system fills the document and **a person checks and posts it**. ## How my extension does it The extension “Local document recognition from photos for 1C” works on a local model through LM Studio: a photo, scan or PDF goes to a model on the user's computer, the document is detected as UPD or TORG-12, the supplier and items are matched, and the document is filled in 30–60 seconds. No internet is needed and data never leaves the computer. It is tested on 1C:Trade Management 11.5 and 1C:Accounting 3.0, and a custom integration is done for other configurations. Details and prices are on the [project page](/raboty/raspoznavanie-dokumentov-1c/) and on [Infostart](https://infostart.ru/marketplace/2700415/). For other 1C work see [1C and accounting systems](/uslugi/1c/). ## FAQ ### Do I need recognition if the supplier uses EDI? No. An electronic UPD loads from XML without recognition and is more accurate than any OCR. Recognition is for paper documents, scans and photos. ### Can the model run without a graphics card? Technically yes, on a CPU, but processing is slower. Check the speed on your own computer with real documents before rolling it out. ### How do I avoid mistakes in tax IDs and totals? Compare the document total with the paper total, check tax IDs against the counterparty catalog and always keep human review before posting. ### How safe is cloud recognition? It depends on the service and your requirements. If documents contain trade secrets, find out where data is stored and processed, or choose a local option. ## Validate Telegram Mini App initData in Python: code and mistakes URL: https://oneswitch.ru/en/blog/proverka-initdata-telegram-mini-app-python/ Date: 2026-10-30 When a Mini App calls your server, you need to be sure the request really came from Telegram for a specific user, and not from an attacker who substituted someone else's `user_id`. For this Telegram signs the **initData** string and your server verifies the signature. ## How validation works A Mini App receives `Telegram.WebApp.initData`, a string like `query_id=...&user=...&auth_date=...&hash=...`. Validation goes like this: 1. Parse the string into key-value pairs (values are URL-decoded). 2. Remove the `hash` field, sort the remaining pairs by key and join them as `key=value` separated by a **newline**. 3. Compute the **secret key**: HMAC-SHA256 where the key is the string `WebAppData` and the message is the bot token. 4. Compute HMAC-SHA256 of the string from step 2 with that secret and compare the result (hex) with the received `hash`. 5. Check that `auth_date` is not older than a reasonable limit. ## Working code ```python import hashlib import hmac import json import time from urllib.parse import parse_qsl def validate_init_data(init_data: str, bot_token: str, max_age: int = 3600) -> dict: """Returns the Mini App data if the signature is valid and fresh, otherwise raises ValueError.""" pairs = dict(parse_qsl(init_data, keep_blank_values=True)) received_hash = pairs.pop("hash", None) if not received_hash: raise ValueError("missing hash") check_string = "\n".join(f"{k}={v}" for k, v in sorted(pairs.items())) secret_key = hmac.new(b"WebAppData", bot_token.encode(), hashlib.sha256).digest() expected = hmac.new(secret_key, check_string.encode(), hashlib.sha256).hexdigest() if not hmac.compare_digest(expected, received_hash): raise ValueError("signature mismatch") if time.time() - int(pairs.get("auth_date", 0)) > max_age: raise ValueError("data expired") if "user" in pairs: pairs["user"] = json.loads(pairs["user"]) return pairs ``` We ran this code on a signed sample, on tampered data, on a wrong token and on a stale `auth_date`: valid data is accepted and the rest is rejected. ## How to send initData to the server The frontend sends the string in a request header and the server validates it on every call: ```javascript fetch("/api/me", { headers: { Authorization: "tma " + Telegram.WebApp.initData } }); ``` The `tma` prefix is a common convention, not a Telegram requirement. An aiohttp example: ```python from aiohttp import web async def me(request: web.Request) -> web.Response: auth = request.headers.get("Authorization", "") if not auth.startswith("tma "): raise web.HTTPUnauthorized() try: data = validate_init_data(auth[4:], BOT_TOKEN) except ValueError: raise web.HTTPUnauthorized() return web.json_response({"user_id": data["user"]["id"]}) ``` In FastAPI the same function plugs in as a dependency (`Depends`) that reads the header and calls `validate_init_data`. ## Common mistakes - **Validating on the client.** The signature must be checked on the server only: the bot token must never reach the frontend. - **Comparing with `==`.** Use `hmac.compare_digest` to avoid a timing attack. - **Forgetting `auth_date`.** Without an expiry check, intercepted old data works forever. - **Wrong key order** or extra fields in the check string. `hash` is not part of the string; the rest are sorted alphabetically. - **Wrong token.** The signature is tied to a specific bot's token. With several bots, store the token with the app. - **Trusting `initDataUnsafe`.** It is the same data without validation. Never use it for authorization. ## Where it is useful Validating `initData` is needed by any Mini App that stores user data: favorites, notification subscriptions, saved searches. That is how the Mini Apps in our projects work: [Da Nang House](/raboty/danang-house/) and [HotTrip](/raboty/hottrip/). If you are building a bot or a Mini App, see [Telegram bots and Mini Apps](/uslugi/telegram-boty-i-mini-app/). ## FAQ ### Can I trust user_id from initDataUnsafe? No. `initDataUnsafe` is parsed data without signature validation. Use only data that passed `validate_init_data` for authorization. ### How long is initData valid? Telegram passes the creation time in `auth_date`, and you decide the lifetime. An hour is enough for ordinary requests; sensitive operations use less. ### What should I do on a “signature mismatch” error? Check that the token belongs to the bot that opened the Mini App, that `hash` is excluded from the check string, and that pairs are sorted by key and joined with a newline. ### Do I need validation if the Mini App only reads public data? If the data is public and not tied to a user, validation is optional. As soon as personal data or actions on behalf of a user appear, it is required. ## Send messages from 1C to Telegram: code, chat_id and pitfalls URL: https://oneswitch.ru/en/blog/otpravka-soobshchenij-iz-1s-v-telegram/ Date: 2026-10-30 Notifications from 1C to Telegram can be set up without paid extensions: you need a bot and a few dozen lines of code. Here is the scheme, the code and the places where people most often go wrong. ## How it works 1. In Telegram, create a bot through **@BotFather** and get a **token**. 2. A user writes to the bot and Telegram assigns them a **chat_id**. 3. 1C calls the **sendMessage** method of the Telegram Bot API over HTTPS, passing the token and chat_id. The hard part is not sending but **mapping**: Telegram lets a bot write only to someone who started the conversation, and only by their chat_id. So 1C must store a “user or employee → chat_id” link. ## Sending a message: code ```bsl Функция ОтправитьВTelegram(Токен, ИдЧата, Текст) Экспорт Данные = Новый Структура("chat_id, text, parse_mode", ИдЧата, Текст, "HTML"); Запись = Новый ЗаписьJSON; Запись.УстановитьСтроку(); ЗаписатьJSON(Запись, Данные); Тело = Запись.Закрыть(); Запрос = Новый HTTPЗапрос("/bot" + Токен + "/sendMessage"); Запрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8"); Запрос.УстановитьТелоИзСтроки(Тело, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать); Соединение = Новый HTTPСоединение("api.telegram.org", , , , , 30, Новый ЗащищенноеСоединениеOpenSSL()); Ответ = Соединение.ОтправитьДляОбработки(Запрос); Если Ответ.КодСостояния <> 200 Тогда ВызватьИсключение "Telegram вернул код " + Ответ.КодСостояния + ": " + Ответ.ПолучитьТелоКакСтроку(); КонецЕсли; Возврат Ответ.ПолучитьТелоКакСтроку(); КонецФункции ``` (The code is in the 1C language: `HTTPConnection` is `HTTPСоединение`, `HTTPRequest` is `HTTPЗапрос`.) Test it on your platform version: method names and constructor parameters can differ in older releases. ## How to find a user's chat_id There are two working ways: - **Manually for yourself or an admin:** write to the bot, then open `https://api.telegram.org/bot/getUpdates` in a browser and find `chat.id` in the response. - **For employees:** the bot offers a “Share contact” button. Telegram sends a phone number, 1C finds the user by it and saves the chat_id in an information register. **Always check that the contact belongs to the sender:** in the contact data `user_id` must equal `from.id`. Otherwise anyone can supply someone else's number and receive their notifications. ## Pitfalls - **The token.** Do not keep it in module text. Put it in a constant with restricted access or a secure store so it does not end up in a configuration dump or Git. - **Limits.** According to Telegram's FAQ, a bot can send about 30 messages per second overall and about one message per second to a single chat. For mass mailings add pauses and a queue. - **Do not block posting.** Move sending to a **background job** or a scheduled job, otherwise a failing internet connection slows down documents. Write errors to the event log. - **Undelivered messages.** If a user blocked the bot, Telegram returns an error: mark such a recipient and do not retry. - **Text format.** With `parse_mode` = `HTML`, escape `<`, `>` and `&` in data taken from the database. ## Incoming messages: webhook or polling If the bot must receive commands (for example “Approve document”), there are two ways: - **Webhook:** Telegram pushes updates to your HTTPS address. It needs a publicly reachable address with a certificate, usually a 1C HTTP service or a separate server. - **Polling getUpdates** from a scheduled job: simpler and needs no public address, but with a delay. ## When it is easier not to write it yourself If you need approvals in the bot, document cards, several databases or a link between a site and a bot, it is easier to move the logic to a separate service (Python or n8n) and keep 1C as the source of events and data. More on integrating 1C with Telegram, sites and other systems in [1C and accounting systems](/uslugi/1c/) and [Telegram bots and Mini Apps](/uslugi/telegram-boty-i-mini-app/). ## FAQ ### Can I send a message to a group or channel? Yes. Add the bot to the group or channel as an administrator and use the group's chat_id (it starts with a minus) or `@channel_name`. ### Do I need an external server to send? No. To send, the 1C server just needs internet access to `api.telegram.org`. An external address is needed only to receive messages through a webhook. ### What if the request from 1C does not go through? Check the 1C server's internet access and proxy, the platform version, the token and the body encoding (UTF-8). Telegram's error text usually says what is missing. ### How do I store the token safely? In a constant or register restricted by roles, not in module text. If the token got into a dump or a repository, reissue it in @BotFather. ## 1C and website data exchange: HTTP service or OData, auth, errors URL: https://oneswitch.ru/en/blog/obmen-1s-s-sajtom-http-servis-odata/ Date: 2026-10-30 A website and 1C usually exchange data in two scenarios: the site pulls the catalog, prices and stock from 1C, and 1C pulls orders and leads from the site. Here are two approaches and the rules that keep the exchange from becoming a source of failures. ## Two approaches: OData and an HTTP service | | **OData (standard interface)** | **HTTP service** | |---|---|---| | What it is | Built-in REST-like access to configuration objects | Your own methods with your own logic | | When to choose | Simple reading and writing of catalogs and documents | You need custom processing: calculations, checks, a response built for the site | | Setup | Enable the standard OData interface composition and publish the database | Create an “HTTP service” object, write handlers, publish | | Downsides | Exposes the 1C structure as is, heavy selections, awkward names | You write and maintain code | A practical rule: **for catalog and stock a custom HTTP service is usually more convenient** with a compact response, while OData fits quick prototypes and administrative tasks. ## OData: a Python reading example Once OData is enabled and the database is published, objects are available at an address like `http://server/base/odata/standard.odata/Catalog_Номенклатура`. ```python import requests BASE = "https://example.com/base/odata/standard.odata" def items(top: int = 10) -> list[dict]: r = requests.get( f"{BASE}/Catalog_Номенклатура", params={"$format": "json", "$top": top}, auth=("integration", "password-from-a-secret-store"), timeout=20, ) r.raise_for_status() return r.json()["value"] ``` Take the login and password from environment variables or a secret store, not from code. (The object name `Catalog_Номенклатура` is the catalog “Nomenclature” in the 1C configuration.) ## HTTP service: a method example In the configurator you create an “HTTP service” object with a root URL and a template. The method handler returns a response with JSON: ```bsl Функция ТоварыGET(Запрос) Данные = Новый Массив; // ... fill the data from the catalog ... Запись = Новый ЗаписьJSON; Запись.УстановитьСтроку(); ЗаписатьJSON(Запись, Данные); Ответ = Новый HTTPСервисОтвет(200); Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8"); Ответ.УстановитьТелоИзСтроки(Запись.Закрыть(), КодировкаТекста.UTF8); Возврат Ответ; КонецФункции ``` The method address is built as `http://server/base/hs/rootURL/template`. Check the syntax on your platform version. ## Security rules - **Do not expose the database to the internet directly.** Put a reverse proxy (for example nginx) in front of 1C with HTTPS and IP restrictions to your site. - **A separate integration user** with a minimal role: only the objects and rights the exchange needs. - **HTTPS is mandatory.** With Basic authentication over HTTP the login and password travel in plain text. - **Keep passwords and tokens out of code.** Use environment variables or a secret store. - **Limit the response size:** pagination and limits so a single request cannot overload the 1C server. ## Reliability rules for the exchange 1. **Idempotency.** Give every order a unique identifier. If a request is sent twice, 1C must understand the order already exists instead of creating a duplicate. 2. **Queue and retries.** Do not write to 1C straight from the site's handler. Save the order on your side and pass it to 1C with a separate process that retries. 3. **Exchange status.** Keep a “sent to 1C” flag and time for each order. It lets you find lost orders and see failures. 4. **Do not block the user.** If 1C is unavailable, the site should still accept the order and send it later. 5. **Versions and compatibility.** When you change a response format, keep the old fields or version the methods (`/v1/`, `/v2/`). 6. **Logs.** Log every call and error, otherwise failure analysis turns into guessing. ## Common mistakes - **Encoding.** Send and receive JSON in UTF-8 and state it in the header. - **Heavy selections.** A “all products” request with attributes and stock hangs a session. Use pages and a separate stock method. - **Sessions and licenses.** Every call uses a database session: check licensing and set timeouts. - **Time zones and dates.** Pass dates in one format and one time zone. - **After a configuration change.** Check that methods are published, rights are in place and the format has not changed. ## What next If you need to connect 1C with a website, an online store, Telegram and other services, see [1C and accounting systems](/uslugi/1c/) and [Integrations and APIs](/uslugi/integracii-i-api/). A related topic: [sending messages from 1C to Telegram](/blog/otpravka-soobshchenij-iz-1s-v-telegram/). ## FAQ ### What is better for a website: OData or an HTTP service? OData suits a quick prototype and administrative tasks. For a working exchange of catalog, stock and orders an HTTP service with a compact response is usually more convenient. ### Can I connect a website to 1C without direct internet access? Yes, and that is the right way. Keep 1C in the internal network and call it through a proxy with IP restrictions or through an intermediary service that talks to 1C itself. ### How do I avoid duplicate orders? Pass a unique order identifier and check it on the 1C side before creating a document. ### What if 1C is temporarily unavailable? Accept the order on the site, keep it in a queue and retry the transfer until you get a confirmation. ## n8n webhook: how to secure it and accept site data without duplicates URL: https://oneswitch.ru/en/blog/n8n-webhook-zashchita-avtorizaciya/ Date: 2026-10-30 A webhook in n8n receives data from a website, a form or another service and starts a workflow. If you leave it unprotected, anyone who learns the address can send requests and trigger your automation. Here is the setup, step by step. ## Test and production URLs The Webhook node has two addresses: - **Test URL** (`/webhook-test/...`) works only while you have pressed “Listen for test event” in the editor. It is for debugging. - **Production URL** (`/webhook/...`) works when the workflow is **activated**. A common mistake: a site form points at the test address, and after you close the editor the data stops arriving. On the site always use the production address. ## Authentication The Webhook node has an **Authentication** setting: Basic Auth, Header Auth or JWT. For requests from a site and from services **Header Auth** is convenient: you create credentials with a header name (for example `X-Webhook-Token`) and a long random value. A request without the right header is rejected. A sample request: ```bash curl -X POST https://n8n.example.com/webhook/lead \ -H "X-Webhook-Token: " \ -H "Content-Type: application/json" \ -d '{"request_id": "7f3c...", "name": "Anna", "contact": "@anna", "msg": "I need a website"}' ``` Important: **never put the secret in page code**, because any visitor can see it. A request with the token must come from your server, not from a browser. If the form is public, send it to your own backend, which then calls n8n. ## Extra protection on the proxy n8n usually sits behind nginx. There you can: - **restrict access by IP** to the `/webhook/...` path (only your server or the sending service); - **limit the request rate** so a flood cannot take down the workflow; - **limit the body size** so you do not accept extra megabytes. This works independently of the token and stops mass guessing attempts. ## How to reply to the site In the Webhook node you set **when** to send the reply: - **Immediately:** fast, but the reply carries no result. Fits lead forms. - **After the last node:** the site waits for the whole processing, and a failure leaves the request hanging. - **With the Respond to Webhook node:** you decide where in the workflow to reply and what to return. A practical rule: **reply as early as possible** (confirm the request was accepted) and do heavy work (writing to a database, sending messages, calling external APIs) after the reply. That way the site does not depend on the speed of the other systems. ## Protection from duplicates and forgery 1. **Request ID.** Send a unique `request_id` (for example a UUID). In the workflow first check whether you already processed it, then act. 2. **Data validation.** Check required fields and length, and do not trust types: a webhook accepts any JSON. 3. **Signature.** If the sender supports a body signature (HMAC), verify it in a Code node. It is more reliable than a shared token. 4. **Limited rights.** The credentials the workflow uses (database, bot) should have minimum permissions. ## A typical flow: a site request into a database and a chat In our housing catalog project it looks like this: a site form sends data to a webhook, n8n validates it and writes it to PostgreSQL, then publishes it to a Telegram group and returns a reply to the site. More about automating the catalog: [Da Nang House](/raboty/danang-house/). For the publishing scheme see [Telegram auto-posting with n8n and PostgreSQL](/blog/avtoposting-v-telegram-n8n-postgresql/). ## What else to check - **n8n updates and editor access:** restrict access to the editor and keep credentials only in the credentials section. - **Execution logs.** Keep error executions so you can see failed requests. - **Failure alerts.** Add a separate workflow that tells you about errors. If you need help with integrations and automation, see [Process automation](/uslugi/avtomatizaciya-processov/) and [Integrations and APIs](/uslugi/integracii-i-api/). ## FAQ ### Can I leave a webhook without authentication? Only if the workflow it runs is safe and changes nothing. Anyone who knows the address can call it. Enable authentication for working workflows. ### Why did data stop arriving? Most often the form points at the test address or the workflow is not activated. Check that the Production URL is used and the workflow is on. ### How do I avoid duplicates on a repeated send? Pass a unique request identifier and check it in the workflow before acting, for example by writing it to a table with a unique key. ### Do I need HTTPS for a webhook? Yes. Tokens and user data must not travel over an open channel, and Telegram and many services require HTTPS. ## 1C invoice recognition without the cloud: UPD and TORG-12 from a photo URL: https://oneswitch.ru/en/blog/lokalnoe-raspoznavanie-dokumentov-v-1s/ Date: 2026-10-30 Accountants and warehouse staff enter supplier invoices into 1C every day: open a document, find the counterparty, type every line, price, quantity and VAT. One document takes 10–15 minutes, and there are dozens of them. ## How it works 1. **Photo or scan.** A phone photo, a scan or a PDF, including multi-page ones. 2. **Recognition.** The extension sends the image to a local AI model, detects the document type (UPD or TORG-12), finds the supplier and matches items from the nomenclature catalog. 3. **Review.** The 1C document is already filled in, and you only review and post it. In my 1C extension the model runs through the free LM Studio program right on the user's computer. One document takes 30–60 seconds. ## Why local and not a cloud OCR - **Data security.** Invoices contain prices, tax IDs and supplier lists. Local processing rules out sending them to someone else's servers. - **Works offline.** The connection is gone, and documents are still processed. - **Control.** Filling rules and accounting policy can be tuned to your database. ## What to consider at launch - The computer needs resources to run the model, so check the requirements first. - Start with typical documents, then add non-standard ones: every new format is configured separately. - Always keep a human review before posting. - Item matching depends on the quality of the catalog, so clean up duplicates and outdated items. The ready extension is tested on 1C:Trade Management 11.5 and 1C:Accounting 3.0, and a custom integration is done for other configurations. Details and prices are on the [project page](/raboty/raspoznavanie-dokumentov-1c/) and on [Infostart](https://infostart.ru/marketplace/2700415/). ## FAQ ### Do I need internet to run it? No. Processing happens on the client's computer, so internet is not required. ### Which documents are supported? UPD and TORG-12 in JPG, PNG and PDF, including multi-page documents. Other document types are added with a separate setup. ### Will it fit my configuration? The extension is tested on UT 11.5 and BP 3.0. For KA, ERP, UNF and customized configurations a custom integration is done. ### Do I still need to check the result? Yes. The extension fills the document, and a person posts it after review. ## llms.txt: an example file, the format and a checklist for your site URL: https://oneswitch.ru/en/blog/llms-txt-primer-formata/ Date: 2026-10-30 The `llms.txt` file is a short guide to your site for language models. It lives in the root (`/llms.txt`) and is written in Markdown. Here are the structure, an example and the limits. ## File format The common format has these parts: 1. **A first-level heading:** the name of the site or project (the required part). 2. **A blockquote with a short summary:** one or two sentences about what the site is. 3. **Optional paragraphs** with important notes. 4. **Second-level sections** with link lists: `- [Name](address): a short note`. 5. **An `Optional` section** for secondary material that can be skipped if there is not enough room. ## Example ```markdown # OneSwitch > Development and automation: websites, Telegram bots and Mini Apps, integrations, 1C and AI agents. Author: Vladimir Kalianov. Language: English. Contact: the /en/kontakty/ page. ## Services - [Telegram bots and Mini Apps](https://oneswitch.ru/en/uslugi/telegram-boty-i-mini-app/): bots, catalogs, subscriptions, notifications. - [1C and accounting systems](https://oneswitch.ru/en/uslugi/1c/): extensions, site exchange, AI document recognition. ## Work - [HotTrip](https://oneswitch.ru/en/raboty/hottrip/): a portal, an AI bot, a Mini App and an automated channel. ## Blog - [Validating Mini App initData](https://oneswitch.ru/en/blog/proverka-initdata-telegram-mini-app-python/): code and mistakes. ## Optional - [Full site text](https://oneswitch.ru/en/llms-full.txt) ``` ## How to write a good file - **Only important pages.** Services, key articles, documentation, contacts. Do not paste the whole sitemap. - **A note for every link.** A short phrase about what is on the page helps a model pick the right one. - **Full addresses** with protocol and domain, without redirects. - **Freshness.** The file must update with the site, otherwise it will list pages that no longer exist. - **Keep it short.** It is a reference, not a copy of the site. For the full text make a separate `llms-full.txt`. ## Generating with a script It is convenient to build the file from the same data as the site. A Python example: ```python def build_llms_txt(title: str, summary: str, sections: dict[str, list[tuple[str, str, str]]]) -> str: """sections: {"Services": [(title, url, note), ...]}""" lines = [f"# {title}", "", f"> {summary}", ""] for name, links in sections.items(): lines.append(f"## {name}") lines += [f"- [{t}]({u}): {d}" for t, u, d in links] lines.append("") return "\n".join(lines) ``` That is how the file on this site is made: it is generated on every build from the list of services, work and articles, so it always matches the content. ## How it differs from other files | File | Purpose | |---|---| | `robots.txt` | Access rules for crawlers: what may and may not be crawled | | `sitemap.xml` | A full list of pages for search engines | | `llms.txt` | A short meaning-level overview of the site for language models | They complement each other. **Structured data** in JSON-LD, which describes pages for search engines and AI, is also useful. ## What to expect `llms.txt` is a community proposal, not a standard every system must support. Not all models and crawlers read it, so **it does not guarantee mentions in answers**. But it costs nothing, helps those who use it and forces you to describe your site clearly. Add it along with the rest of the preparation: [GEO and llms.txt](/blog/llms-txt-i-geo-seo-dlya-nejrosetej/). Service: [SEO and AI optimization](/uslugi/seo-i-ai-optimizaciya/). ## FAQ ### Where should llms.txt live? In the site root at `https://your-domain/llms.txt`, like `robots.txt`. ### Should I allow AI bots to crawl my site? If you want to be found through AI, do not block them in `robots.txt`. For paid or private content set up restrictions. ### Does llms.txt replace the sitemap? No. A sitemap is for search engines, llms.txt gives models a short overview. It is best to have both. ### What is llms-full.txt? An additional file with the full text of key pages in one document. It is useful when a model needs to read the whole site without following links. ## A Telegram Mini App catalog: API design, filters and subscriptions URL: https://oneswitch.ru/en/blog/katalog-v-telegram-mini-app-arhitektura/ Date: 2026-10-30 A catalog inside Telegram is convenient because users never leave the messenger: they search, save a search and get notifications about new items. Here is the architecture behind such a catalog, using rentals and flights as examples. ## Three parts of the system 1. **The catalog API:** returns items by filters. 2. **Authorization:** identifies the user from the signed Mini App data. 3. **A subscription worker:** matches new items against saved criteria and sends notifications. The data lives in one database, so the catalog on the site and in the Mini App is always the same and updates show up immediately. ## The catalog API A minimal set of methods: | Method | Purpose | |---|---| | `GET /api/items` | A list with filters, sorting and pagination | | `GET /api/items/{id}` | An item card: photos, description, map, contact | | `GET /api/places` | Suggestions for entering a district, city or destination | | `POST /api/subscriptions` | Save search criteria and enable notifications | | `GET /api/subscriptions` | A user's subscriptions | | `DELETE /api/subscriptions/{id}` | Turn a subscription off | Tips: - **Cursor pagination** instead of page numbers: the list does not “jump” when new items appear. - **Filters as query parameters:** district, type, price range, sorting. Validate the values on the server. - **Database indexes** on filter and sort fields. Without them a catalog with thousands of rows will slow down. - **Thumbnails instead of originals.** Photos in a list must be light; originals load in the card. - **Caching** for frequent requests: popular filters can be cached for minutes. ## Authorization Any request that works with a user (subscriptions, favorites) must carry the signed Mini App data, which the server validates. A detailed walkthrough with code: [how to validate initData in Python](/blog/proverka-initdata-telegram-mini-app-python/). Public catalog methods can work without authorization. ## Subscriptions by criteria A user saves a search: district, type, price range. It is convenient to store the criteria as JSON next to the user identifier: ```sql CREATE TABLE subscriptions ( id bigserial PRIMARY KEY, user_id bigint NOT NULL, criteria jsonb NOT NULL, -- {"district": "Son Tra", "type": "studio", "price_max": 10000000} active boolean NOT NULL DEFAULT true, last_notified_item bigint NOT NULL DEFAULT 0 ); ``` A worker runs on a schedule or on the “new item appeared” event. For each new item it finds matching subscriptions, sends a message and remembers the last notified item so it does not send repeats. Principles: - **Do not duplicate notifications.** Store what has already been sent to each user. - **Group them.** If many items appeared, send one digest instead of ten messages. - **Give an easy exit.** Every notification should have a button to turn the subscription off. - **Respect Telegram limits** and handle delivery errors: the user may have blocked the bot. ## A notification that opens the app The message is sent by the bot, and a button with `web_app` opens the new item's card in the Mini App. How to send such a button is described in the article about [bot buttons and menus in n8n](/blog/telegram-bot-n8n-knopki-menu-mini-app/). ## What to show and how to update - **Fresh data matters.** In our rental catalog for Da Nang the database refreshes automatically every 15 seconds, and new listings reach the catalog and the group without manual work. - **Show the date added** and a “today” badge for new items. - **Keep the interface state:** remember the chosen filters so the user returns to the same search. ## What we built The Mini Apps in the [Da Nang House](/raboty/danang-house/) (a housing catalog with subscriptions) and [HotTrip](/raboty/hottrip/) (hot flights with a price radar) projects follow this scheme. If you need a catalog in Telegram for your niche, see [Telegram bots and Mini Apps](/uslugi/telegram-boty-i-mini-app/) and [Web applications](/uslugi/veb-prilozheniya/). ## FAQ ### Do I need a separate website if I have a Mini App? Preferably yes: the site is for Google and Yandex search, while the Mini App retains users and sends notifications. The data is shared. ### How many items can such a catalog handle? Thousands of items are served without problems with proper indexes, pagination and thumbnails. Our rental catalog has more than three thousand. ### How do I keep the catalog updated automatically? Data sources connect to the database on a schedule or via webhooks, and new records immediately appear in the API and in the subscription worker. ### Can I do subscriptions in the bot only, without a Mini App? You can, but a Mini App is more convenient for choosing criteria and managing subscriptions. The bot remains the notification channel. ## No duplicates in auto-posting: a key, ON CONFLICT and a queue URL: https://oneswitch.ru/en/blog/dedup-v-avtoposting-n8n-postgresql/ Date: 2026-10-30 Auto-posting and integrations sooner or later start sending repeats: a workflow ran twice, a service retried a request, an export arrived with the same data. The most reliable protection lives in the database, not in the workflow itself. ## Where duplicates come from - **A repeated run** on a schedule or by hand. - **Repeated webhook delivery:** the sender got no reply and sent the request again. - **Overlapping sources:** the same offer arrives from two places. - **A failure in the middle:** the message went out but the mark was not saved, so on a retry it goes out again. ## Step 1: a unique offer key Come up with a stable key by which two records count as the same offer. For flights it is route, date and price range, for listings address and price, for leads the request ID. ```sql CREATE TABLE offers ( id bigserial PRIMARY KEY, dedup_key text NOT NULL UNIQUE, payload jsonb NOT NULL, status text NOT NULL DEFAULT 'new', -- new, sending, sent, failed created_at timestamptz NOT NULL DEFAULT now(), published_at timestamptz ); ``` The `UNIQUE` constraint will not let the same thing in twice, even if two workflows run at the same time. ## Step 2: inserting without duplicates ```sql INSERT INTO offers (dedup_key, payload) VALUES ($1, $2) ON CONFLICT (dedup_key) DO NOTHING RETURNING id; ``` If the record is new the query returns its `id`. If the key already exists the result is empty and you simply skip the offer. This works without a separate “does it exist” check, which is itself prone to races. ## Step 3: the send queue Do the sending as a separate step that takes records from the queue. To keep two workers from taking the same record use a row lock that skips busy rows: ```sql UPDATE offers SET status = 'sending' WHERE id = ( SELECT id FROM offers WHERE status = 'new' ORDER BY id FOR UPDATE SKIP LOCKED LIMIT 1 ) RETURNING id, payload; ``` `FOR UPDATE SKIP LOCKED` locks the chosen row and skips those already taken by another worker. Each worker gets its own record. ## Step 4: statuses and retries After sending, mark the result: ```sql UPDATE offers SET status = 'sent', published_at = now() WHERE id = $1; -- on error: UPDATE offers SET status = 'failed' WHERE id = $1; ``` Now any step can be safely repeated: - records with the `failed` status can be sent again; - records stuck in `sending` for more than a few minutes are returned to `new` by a separate job (so you do not lose messages when a worker crashes). ## Nuances - **A message may have gone out without the mark.** If the process died between sending and updating the status, a retry sends the message again. For critical cases store the sent message ID and check before retrying. For channel posts a small chance of a repeat is usually acceptable. - **The key must be stable.** Do not include fields that change on every export (the request time). - **Old records.** Clean or archive the table on a schedule: the uniqueness constraint works while the record exists. If you need to remember a key longer, keep only keys. - **A pause between sends** protects against Telegram limits. ## How it is built into n8n In an n8n workflow these are PostgreSQL nodes: an insert with `ON CONFLICT`, a queue select with a lock, sending to Telegram and a status update. The state lives in the database, so restarting the workflow breaks nothing. The general pipeline scheme is in [Telegram auto-posting with n8n and PostgreSQL](/blog/avtoposting-v-telegram-n8n-postgresql/), and receiving data from a site in [securing an n8n webhook](/blog/n8n-webhook-zashchita-avtorizaciya/). This approach is used in [HotTrip](/raboty/hottrip/) and [Da Nang House](/raboty/danang-house/). Service: [Content and social media](/uslugi/kontent-i-soczseti/). ## FAQ ### Why can't I check for duplicates in the workflow? A “does a record exist” check and an insert are not atomic: two runs can both decide there is no record. A uniqueness constraint in the database closes this without races. ### What if offers have no natural key? Build one from a set of fields (source, the source's ID, date) and store it as a hash or a string. The main thing is that the key does not change on a repeated export. ### How do I handle “stuck” records? With a periodic job return records with the `sending` status older than a set time back to `new` and write that to a log. ### Does this work for other databases? The idea is universal but the syntax differs. `ON CONFLICT` and `SKIP LOCKED` are in PostgreSQL; other databases have their own equivalents. ## Telegram auto-posting with n8n and PostgreSQL: pipeline design URL: https://oneswitch.ru/en/blog/avtoposting-v-telegram-n8n-postgresql/ Date: 2026-10-30 Auto-posting is for projects with many offers and too little time to publish by hand: flight deals, listings, news. Below is the scheme I use in projects with Telegram channels. ## What the pipeline consists of 1. **Collection.** A request to the source API on a schedule, for example every two hours. 2. **Storage.** Every offer is saved to PostgreSQL with a unique key, so duplicates cannot get through. 3. **Preparation.** Digests are built from records, photos are picked and, if needed, a video is rendered. 4. **Queue.** Posts go out in batches with a pause between messages so Telegram limits are not hit. 5. **Verification.** After sending, the workflow makes sure the message is live and writes errors to a log. ## Why n8n and PostgreSQL n8n shows the chain visually and lets you change logic quickly. PostgreSQL keeps the state: what is already published, what is queued and what failed. Without a database a workflow forgets the past and posts repeats. ## What to watch at launch - Put a unique key on an offer, for example route plus date. - Pause between sends and retry on errors. - Add a failure notification to a private chat. - Keep tokens in environment variables, not in the workflow. ## FAQ ### Can I publish to several channels at once? Yes. Add a destination field to the table and move sending into a separate step that works through the queue. ### What is better: n8n or a custom script? For a typical chain n8n starts faster and is easier to maintain. If the logic is complex or volumes are large, Python code is more reliable. ### How do I avoid being blocked for spam? Respect the limits, do not send identical messages in a row and group offers into digests. ## Aviasales API in Python: flight prices via Travelpayouts URL: https://oneswitch.ru/en/blog/aviasales-travelpayouts-api-na-python/ Date: 2026-10-30 If you are building a site, bot or Mini App with flights, the simplest price source is the **Travelpayouts Data API** (Aviasales). Below is a Python example, typical requests and the limits we ran into while working on HotTrip. ## What the Data API is and how it differs from live search The Data API returns **cached prices** collected from Aviasales user searches. It is fast and free, but it is not the same as a real-time search: - a price can be **stale**: according to third-party wrappers, data comes from searches of roughly the last two days; - for rare routes and dates there may be **no data**; - the final price on the purchase page may differ. Travelpayouts has a separate API for live search with different access conditions; see the documentation. For a showcase “from X” and destination lists the Data API is usually enough. ## What you need - A **Travelpayouts** account and a **token** (issued in your dashboard). - Your affiliate **marker** for links, if you want a commission. - Python and the `requests` library. Pass the token in the `x-access-token` header and keep it in an environment variable, not in code. ## Prices by route and dates The main method is `GET https://api.travelpayouts.com/aviasales/v3/prices_for_dates`. ```python import os import requests API = "https://api.travelpayouts.com/aviasales/v3/prices_for_dates" TOKEN = os.environ["TRAVELPAYOUTS_TOKEN"] def cheapest(origin: str, destination: str, month: str, limit: int = 10) -> list[dict]: """Cheapest offers. origin/destination: IATA codes, month: '2026-12'.""" r = requests.get( API, headers={"x-access-token": TOKEN}, params={ "origin": origin, "destination": destination, "departure_at": month, "sorting": "price", "unique": "false", "currency": "rub", "limit": limit, }, timeout=10, ) r.raise_for_status() return r.json().get("data", []) for offer in cheapest("MOW", "IST", "2026-12"): print(offer["departure_at"][:10], offer["price"], offer.get("airline"), offer.get("transfers")) ``` The response is a list of offers. Each usually has a price, an airline, a departure date, the number of transfers and a `link` field with a relative address of the Aviasales search page. Check exact fields and current parameters in the Travelpayouts documentation: they can change. ## Popular destinations from a city For a “Where to fly” block, `GET /v1/city-directions?origin=MOW¤cy=rub` is convenient. It returns the destinations from a city in one request, which is faster than looping over routes yourself. ## City and airport codes Use IATA codes. **MOW** means Moscow as a whole (all airports), **SVO** is one airport. For input suggestions there is the autocomplete `https://autocomplete.travelpayouts.com/places2?term=...&locale=en`, which returns cities and airports. ## Links and the affiliate marker The `link` field contains a path: build the full address as `https://www.aviasales.ru` + `link` and add your affiliate marker. Then clicks are counted in your dashboard. For short links in Telegram the API has a method to create shortened affiliate links. ## Pitfalls from practice 1. **Cache on your side.** Store responses in a database and refresh them on a schedule instead of on every user request: it is faster and saves limits. 2. **Empty responses.** For some routes there is no data. Show a clear message and neighbouring dates or destinations. 3. **Freshness.** Store the time a price was received and show it as “from”. Warn that the final price on the purchase page may differ. 4. **Timeouts and errors.** Set a timeout and retry on failure. Do not make a user wait for an external API. 5. **Currency and language.** The `currency` parameter controls the currency of prices; for different countries store prices per currency. ## Where this is used On top of the Data API we built a portal, a Telegram bot with flight search and price subscriptions, a Mini App and an automated channel that publishes fresh offers every two hours. Details are in the [HotTrip](/raboty/hottrip/) project and in [Integrations and APIs](/uslugi/integracii-i-api/) and [Scraping and data](/uslugi/parsing-i-dannye/). ## FAQ ### Is a paid plan required for the Data API? A Travelpayouts token is issued in the partner dashboard. Access conditions for different APIs change, so check the current limits in the Travelpayouts documentation. ### Are Data API prices a live search? No. They are cached data from user searches, so a price can differ from what you see at purchase. ### How do I earn a commission on sales? Add your affiliate marker to Aviasales links. Then purchases through your links are counted in the Travelpayouts dashboard. ### Can I call the API directly from a browser? Not recommended: the token would be visible to everyone. Call the API from a server and give the client only the data it needs. ## Telegram Mini App or a website: what to choose for a catalog URL: https://oneswitch.ru/en/blog/telegram-mini-app-ili-sajt/ Date: 2026-10-29 When you need a catalog, say of housing, tickets or services, the question comes up: build a website, a Mini App or both. The short answer: both, with different roles. ## What a Mini App gives you - It opens inside Telegram in one tap, with no registration. - It knows the user, so saving searches and subscriptions is easy. - It can send notifications through the bot when new items appear. - It looks great on a phone, where most of the audience sits. ## What a website gives you - It is found in search and in AI answers. - You can place articles, guides and a page for every destination on it. - It works without Telegram and is convenient on a computer. ## How to connect them The site brings people from search, and the buttons lead to the bot and the Mini App, where a person saves criteria and gets notifications. The data lives in one database, so the catalog on the site and in the Mini App is always the same. ## What you need technically 1. A shared database and API. 2. A bot with commands, subscriptions and broadcasting. 3. A Mini App in HTML and JavaScript that reads the API. 4. A site with SEO markup and a catalog. ## FAQ ### Is a Mini App hard to build? A basic version with a catalog and filters takes a couple of weeks if the API already exists. The hardest parts are the data and notifications, not the interface. ### Do I need a Mini App if I have a bot? A bot is good for short scenarios. When you need filters, photos and item cards, a Mini App is noticeably more convenient. ### Is a Mini App indexed by search engines? No, so SEO traffic comes from the website, while the Mini App works for retention and repeat visits. ## llms.txt and GEO: how to prepare a site for AI answers URL: https://oneswitch.ru/en/blog/llms-txt-i-geo-seo-dlya-nejrosetej/ Date: 2026-10-28 More and more people get answers not from a list of links but from a neural network. To appear in those answers, a site must be prepared as carefully as for regular search. ## What GEO is GEO (Generative Engine Optimization) is optimizing content so that language models can find a page, understand it and quote it correctly. It does not replace SEO, it complements it. ## What to do in practice 1. **Give a short answer at the start.** A “Summary” block of one or two sentences is easy to quote. 2. **Add structured data.** Article, FAQPage, Service and BreadcrumbList in JSON-LD describe a page in machine language. 3. **Open access for AI bots.** Allow the bots you need in robots.txt and point to your sitemap. 4. **Add llms.txt.** A plain-text file in the site root with a project description and links to the main pages. 5. **Offer Markdown versions.** Clean text without layout is easier to parse. 6. **Write with facts.** Dates, numbers, names and sources increase trust and the chance of being quoted. ## What to expect There is no guarantee of getting into answers, just like in regular SEO. But a site with clear structure and markup is easier to read, which means it has more chances. ## FAQ ### Is llms.txt mandatory? No, it is an optional format and not every system uses it. But it costs nothing and helps those who read it. ### How is GEO different from SEO? SEO fights for a position in search results, GEO for being mentioned and quoted in an answer. Many techniques overlap: structure, facts, markup. ### Should I block AI bots? If you want to be found through AI, do not block them. If content is paid or private, configure restrictions in robots.txt. ## How much a website and automation cost: what the price is made of URL: https://oneswitch.ru/en/blog/skolko-stoit-sajt-i-avtomatizaciya/ Date: 2026-10-27 The question “how much does a website cost” is like “how much does a renovation cost”: without details only a range can be named. Here is what builds that range. ## What affects the price - **Scope.** A landing page and a catalog of thousands of items are different tasks. - **Integrations.** Every link with CRM, payments, 1C or a messenger adds work and tests. - **Data.** Collection, cleaning and storage often take more time than the interface. - **Reliability.** Logs, retries, error notifications and autotests cost extra but pay off. - **Design.** Ready-made solutions are cheaper than custom artwork. - **Deadlines.** Urgent work usually costs more. ## How not to overpay 1. Start with the main scenario and launch it first. 2. Describe the task in your own words: what should happen and for whom. 3. Agree on stages and payment by results. 4. Ask for the source code and access right away. ## Reference points A landing page is usually done in 5–7 days, a multi-page site or a web app in 3–6 weeks, a single automation scenario in 2–10 days. Current price ranges are in the [Pricing section](/ceny/). ## FAQ ### Why can't you name an exact price right away? Because it depends on details. After a short brief I fix scope, timing and cost before work starts. ### What costs more: a website or automation? A website often costs more because of design and content, while automation depends on the number of steps and services. Compare by the task. ### Are there hidden payments? Only external services are paid separately: domain, hosting, APIs and subscriptions. I name their cost in advance.