Нет документации по API? Не беда!
Захожу на сайт ЛК самозанятого, открываю консоль разработчика (вкладка Network → Fetch/XHR), авторизуюсь и наблюдаю что-то страшное... Здесь отображаются все запросы, которые браузер отправляет на сервер.

Регистрирую покупку вручную, к списку добавляется запрос income, а на экране появился чек.
 

Нажимаем на incomeи разбираем подробнее:
Это POST-запрос, принимающий JSON с данными клиента (вкладка Payload) и возвращающий УИД чека (вкладка Response/Preview)

Сам чек появляется через GET-запрос print, он также появился в списке, а во вкладке Preview доступно его изображение.
URL запроса print: https://lknpd.nalog.ru/api/v1/receipt/ваш_ИНН/УИД_чека/print
Авторизация
ЛК самозанятого использует OAuth2 с Bearer-токеном. При каждом запросе нужно передавать access_token в заголовке, его можно увидеть в любом запросе из списка. 
Этот токен живёт 1 час, поэтому его нужно регулярно обновлять.

 
Как получить access_token?
Через запрос на /api/v1/auth/token с таким JSON:
{
  "deviceInfo": {
    "sourceDeviceId": "*******",
    "sourceType": "WEB",
    "appVersion": "1.0.0",
    "metaDetails": {
      "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
    }
  },
  "refreshToken": "ваш_refresh_token"
}
Как видим, что в запросе для получения access_token закрался еще один refresh_token.
 
Да кто этот ваш refresh_token?
Это токен обновления, который живёт около года. Получить его можно:
- 
	Через POST запрос на /api/v1/auth/lkfl, где тело:{ "deviceInfo": { "sourceDeviceId": "*******", "sourceType": "WEB", "appVersion": "1.0.0", "metaDetails": { "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"} }, "username": "*******", "password": "*******" }В ответе будет refresh_token. 
- 
	"Ленивым" способом: взять из запроса verifyиз списка при авторизации и записать в регистр сведений ТокеныАвторизации или в константу, но его всё равно нужно обновлять раз в год вручную.
 
Логика работы с токенами
Перед каждым запросом проверяю:
- 
	Не истёк ли refresh_token
- 
	Не истёк ли access_token
 При необходимости обновляю их.
Пример кода на 1С для обновления access_token:
Функция AccessToken(Соединение, RefreshToken) Экспорт
 
    МенеджерЗаписи           = РегистрыСведений.ТокеныАвторизации.СоздатьМенеджерЗаписи();
    МенеджерЗаписи.Ресурс    = Соединение.Сервер;
    МенеджерЗаписи.ТипТокена = Перечисления.ТипыТокенов.AccessToken;
    МенеджерЗаписи.Прочитать();
    
    Если Не ИстекСрокДействия(МенеджерЗаписи.СрокДействия) И МенеджерЗаписи.Токен <> Неопределено Тогда
        
        Возврат МенеджерЗаписи.Токен;
    Иначе
        JSONАвторизации = ПолучитьJSONАвторизации(RefreshToken); //строка json вида из пункта access_token
        
        ЗапросPOST = Новый HTTPЗапрос();
        ЗапросPOST.АдресРесурса = "/api/v1/auth/token";
        ЗапросPOST.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
        ЗапросPOST.УстановитьТелоИзСтроки(JSONАвторизации, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
        
        Ответ = Соединение.ОтправитьДляОбработки(ЗапросPOST);
        
        Если Ответ.КодСостояния = 200 Тогда
            ОтветСтрокой = Ответ.ПолучитьТелоКакСтроку();
            Чтение = Новый ЧтениеJSON;
            Чтение.УстановитьСтроку(ОтветСтрокой);
            Объект = ПрочитатьJSON(Чтение, Истина);
            Token = Объект["token"];
            
            МенеджерЗаписи.СрокДействия = ТекущаяДатаСеанса() + 3600;
            МенеджерЗаписи.Токен        = Token;
            МенеджерЗаписи.Записать();
            
            Возврат Token;
        Иначе
            Возврат Неопределено;
        КонецЕсли;
    КонецЕсли;
КонецФункции
Пример формирования продажи:
JSONПродажи = ПолучитьJSONПродажи(Источник.Услуга, Источник.Оплачено); //строка json вида из пункта запроса income
ЗапросPOST  = Новый HTTPЗапрос();
ЗапросPOST.АдресРесурса = "/api/v1/income";
ЗапросPOST.Заголовки.Вставить("Authorization", "Bearer " + AccessToken);
ЗапросPOST.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
ЗапросPOST.УстановитьТелоИзСтроки(JSONПродажи, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ = HTTP.ОтправитьДляОбработки(ЗапросPOST);
Если Ответ.КодСостояния = 200 Тогда
    ОтветСтрокой = Ответ.ПолучитьТелоКакСтроку();
    Чтение = Новый ЧтениеJSON;
    Чтение.УстановитьСтроку(ОтветСтрокой);
    Объект = ПрочитатьJSON(Чтение, Истина);
    IDЧека = Объект["approvedReceiptUuid"];
    
    // Отправка чека ученику в Telegram
    ОбменТелеграм.ЗаписатьСсылкуВОчередьОтправки(
        "Чек оплаты занятия", 
        "https://lknpd.nalog.ru/api/v1/receipt/" + INN + "/" + IDЧека + "/print",
        ОбщегоНазначенияСервер.РеквизитОбъекта(Источник.Ученик, "ТелеграмID"));
Иначе
     ЗаписьЖурналаРегистрации("ФормированиеЧекаОплаты",
        УровеньЖурналаРегистрации.Ошибка, 
        Источник.Занятие,
        ,
        СтрШаблон("Ошибка формирования чека оплаты. Код состояния: %1, Тело: %2",
            Ответ.КодСостояния,
            ОтветСтрокой));
КонецЕсли;
Вступайте в нашу телеграмм-группу Инфостарт
 
                                    