Back to Home

Universal API for receiving information on checks

Federal Tax Service · check verification · universal api for check verification · API

Universal API for receiving information on checks

    Hello to the residents of Habr.

    In this article, I would like to talk about the API for receiving checks, which we did not provide to everyone the beloved Federal Tax Service.

    When the QR codes appeared on the receipts, I thought “Wow, how cool! You scan the code and see if not all the info on the check, then a link to it. ” And what was my disappointment when I scanned such a code I saw something like

    t=20180518T220500&s=975.88&fn=8710000101125654&i=99456&fp=1250448795&n=1

    But I did not get upset and thought that the Federal Tax Service had taken care of us and provided an API for receiving such information. Googling for some time, I realized that the Federal Tax Service provided us with only a mobile application to check the check and view the information that came to them from the store.

    But! There is one more link between the store and the tax office - OFD- Those who process check information received from stores and send it to the tax office. So they provide the API to get the information we need. Not all. And not always for free.

    Judging by the information from Wikipedia, as of March 1, 2018, 17 OFDs were registered. Let's say 10 of them provide an open and free API. Given that we do not know with which OFD a particular store works, it will be necessary to walk through API 10 fiscal data operators. Far from the best option.

    After some time, I accidentally stumbled upon an application (not from the Federal Tax Service), which receives information on the check using the QR code from the check. But they will not “run through” all OFDs and collect information from there, I thought. Again went to Google and came across such an answer .

    It seemed that after this answer you could end the impromptu investigation, but I still had questions:

    • What happens if other headers are used?
    • What if the user is not registered? Download the mobile application and register? (The FTS website does not provide the opportunity to register in this context)
    • And if you forgot your password?

    Launching Android Device Monitor and SoapUI, I began to understand. I post here all the generalized information that I managed to get. The FTS provides the following public API:

    registration
    POST
    https://proverkacheka.nalog.ru:9999/v1/mobile/users/signup
    Content-Type: application / json; charset = UTF-8

    Content:

    {"email":"[email protected]","name":"SomeName","phone":"+79991234567"}

    All parameters are required.

    If the result is successful, then the user is created, an SMS with a password is sent to the specified number, and 204 No content is returned.

    If the user already exists, 409 Conflict and the message "user exists" are returned.
    If the phone number is incorrect, then 500 Internal Server Error and the message “failed with code 20101” are returned.

    If the email address is incorrect, then 400 Bad Request is returned and the message "[" Object didn't pass validation for format email: <email address you specified> "]".
    If the email address is already in use and the phone is not there, then no errors occur and registration is successful.

    Login
    GET
    https://proverkacheka.nalog.ru:9999/v1/mobile/users/login

    The pre-emptive Basic Authorization is sent in the header, where the username is the phone number, in the form "+79991234567", and the password is the code received in SMS during registration or password recovery.

    If all is well, then 200 OK and a json message will be returned

    {
       "email": "<адрес электронной почты, указанный при регистрации>",
       "name": "<имя, указанное при регистрации>"
    }

    If you specify an incorrect phone number or password, then 403 Forbidden and the message "the user was not found or the specified password was not correct" will be returned.

    If you do not provide a phone number and / or password, nothing will be returned.

    Password recovery
    POST
    https://proverkacheka.nalog.ru:9999/v1/mobile/users/restore
    Content-Type: application / json; charset = UTF-8

    Content:

    {"phone":"+79991234567"}

    If the phone number is found, then 204 No Content is returned and SMS with a new password comes to the phone.

    If the phone number is not found or the number is incorrect, then 404 Not Found and the message "the user was not found" are returned.

    Checking the existence of a check
    GET
    /operations/1/tickets/<%D0%BD%D0%BE%D0%BC%D0%B5%D1%80%20%D0%A4%D0%94>?fiscalSign=<%D0%BD%D0%BE%D0%BC%D0%B5%D1%80%20%D0%A4%D0%9F%D0%94>&date=2018-05-17T17:57:00&sum=3900">https://proverkacheka.nalog.ru:9999/v1/ofds/*/inns/*/fss/< FN number> / operations / <type of cash receipt> / tickets / <FD number>? FiscalSign = <FD number > & date = 2018-05-17T17: 57: 00 & sum = 3900
    Where

    • FN number (Fiscal Number) - 16-digit number. For example 8710000100518392
    • FD number (Fiscal document) - up to 10 characters. For example 54812
    • FPD Number (Document Fiscal Tag, also known as FP) - up to 10 characters. For example 3522207165
    • Type of cash receipt. In the check it is marked as n = 1 (receipt) and n = 2 (return of receipt)
    • Date - date from the check. The format may vary. I tried to flip the date (i.e. 17-05-2018), put a space instead of T, delete seconds
    • Amount - the amount from the check in kopecks

    If the check is found, then 204 No Content will be returned.
    If the check is not found, then 406 Not Acceptable will be returned.
    If the date / amount is incorrect or does not match the date / amount indicated on the check, then 406 Not Acceptable is returned. In this case, seconds are not taken into account.
    If the date / amount parameter is not specified, then 400 Bad Request and the message "[" Missing required property:"]".

    Getting detailed information on a check
    GET
    /tickets/<%D0%9D%D0%BE%D0%BC%D0%B5%D1%80%20%D0%A4%D0%94>?fiscalSign=<%D0%9D%D0%BE%D0%BC%D0%B5%D1%80%20%D0%A4%D0%9F%D0%94>&sendToEmail=no">https://proverkacheka.nalog.ru:9999/v1/inns/*/kkts/*/fss/<FN number> / tickets / <ФД number>? FiscalSign = <ФПД number> & sendToEmail = no
    Where

    • FN number (Fiscal Number) - 16-digit number. For example 8710000100518392
    • FD number (Fiscal document) - up to 10 characters. For example 54812
    • FPD Number (Document Fiscal Tag, also known as FP) - up to 10 characters. For example 3522207165

    It is also mandatory to specify at least empty device-id and device-os headers.
    If incorrect user data is specified, 403 Forbidden is returned and the message "the user was not found or the specified password was not correct".

    If you do not specify a phone number and / or password, then nothing will be returned.

    If the check is not found, then 406 Not Acceptable is returned. Also, the check may not be found if it was received long ago. The Federal Tax Service does not store information on checks for all the time. At the time of this writing, the Federal Tax Service kept detailed information for about 2-3 months.

    If before the call to this method there was no check of the existence of the check, then 202 Accepted will be returned (without messages and any content). When you call again, the information on the check will be returned.

    If you try to substitute the value "yes" in the "sendToEmail" parameter, then 500 Internal Server Error and the message "connect ECONNREFUSED 127.0.0.1-00-0065" will be returned. If you try to substitute other values ​​("true", 1, etc.), 400 Bad Request will be returned and the message "[" No enum match for: <value you tried to pass> "]".

    If all is well, then 200 OK will return and the contents in json format will look something like this:

    {"document": {"receipt": {
       "operationType": 1,
       "fiscalSign": 3522207165,
       "dateTime": "2018-05-17T17:57:00",
       "rawData": "AwAzAREEEAA4NzEwMDAwMTAwNTE4MzEzDQQUADAwMDExOTM1MTQwNDE0MDUgICAg+gMMADc4MjU3MDYwODYgIBAEBAAJ2gAA9AMEAGzC/Vo1BAYAMQTSDyLSDgQEABYBAAASBAQAogAAAB4EAQAB/AMCADwPPAQPAD0EAwCKrqQ+BAQARzYzNyMERQAGBCcAKjM0OTIyNzcgTkVTVC6MruAuTUFYSUIukZKQgJeAkoWLLjE0MKyrNwQCAJ8P/wMEAAZAQg8TBAIAnw9PBAIAbAH9Aw4AhK6ro+PopaKgIICtraAHBAIAPA85BAEAAE8EAgBsARgEDACAo+Cu4q7goyCOjo7xAyoANjIwMDE3LCCjLiCFqqDipeCoraHj4KMsIOOrLiCAp6itoCwgpC4gMTimHwQBAAE=",
       "totalSum": 3900,
       "nds10": 364,
       "userInn": "7825706086",
       "taxationType": 1,
       "operator": "<Данные кассира>",
       "fiscalDocumentNumber": 54812,
       "properties": [   {
          "value": "G637",
          "key": "Код"
       }],
       "receiptCode": 3,
       "requestNumber": 162,
       "user": "Агроторг ООО",
       "kktRegId": "0001193514041405",
       "fiscalDriveNumber": "8710000100518392",
       "items": [   {
          "sum": 3999,
          "price": 3999,
          "name": "*3492277 NEST.Мор.MAXIB.СТРАЧАТЕЛ.140мл",
          "quantity": 1,
          "nds10": 364
       }],
       "ecashTotalSum": 0,
       "retailPlaceAddress": "620017, г. Екатеринбург, ул. Азина, д. 18ж",
       "cashTotalSum": 3900,
       "shiftNumber": 278
    }}}

    Where

    • all amounts are in kopecks
    • cashier data in different stores have different formats (in one case “Last Name First Name” may return, in another “Last Name I. Position”
    • the order of elements may vary
    • different stores use different sets of parameters, and if some parameter is returned in the check from one store, then it is not a fact that this parameter will be in the check from another store
    • store address format may vary

    Another example of a returned check
    {"document": {"receipt": {
       "cashTotalSum": 0,
       "fiscalSign": 1301551154,
       "nds18": 4859,
       "operationType": 1,
       "userInn": "7728029110",
       "dateTime": "2018-05-18T22:05:00",
       "fiscalDocumentNumber": 12654,
       "receiptCode": 3,
       "ecashTotalSum": 97588,
       "nds10": 5976,
       "requestNumber": 395,
       "retailPlaceAddress": "г.Екатеринбург, ул.Сулимова, д.50",
       "fiscalDriveNumber": "871000010459859",
       "taxationType": 1,
       "user": "АО ТД Перекресток",
       "operator": "<Данные кассира>",
       "items":    [
                {
             "sum": 3799,
             "quantity": 1,
             "price": 3799,
             "name": "18074 Укроп пакет 100г",
             "nds10": 345
          },
                {
             "sum": 7490,
             "quantity": 0.872,
             "nds18": 1143,
             "name": "2000339 Яблоки СЕЗОН.ПРЕДЛОЖЕНИЕ 1кг",
             "price": 8590
          }
       ],
       "totalSum": 97588,
       "rawData": "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",
       "shiftNumber": 262,
       "kktRegId": "0001248888049341"
    }}}



    I don’t see much meaning in the login, but it is used in their mobile application. Perhaps in the future it will come in handy for something.

    Who is interested in an example of implementing a connection to this API, here is a link to the github project of a library written in C #.

    For all questions or comments, please comment.

    UPD After a small check, it turned out that the Federal Tax Service does not store detailed information on all checks. At least on 05/22/2018 I was not able to get the full check from December 2017, January and February 2018, despite the fact that the OFD has this information and the FTS mobile application reports that the check is correct. For March 2018, a check has already been received.

    UPD As users of IvanG and neoman36 noticed, n = 1 is the "Type of cash receipt". 1 - means “parish”, 2 - “Return of parish”. The same number must be inserted when checking the existence of a check.

    UPD As a user of Echo77 noted , starting in December 2018, the API began to return the response code 451 “Illegal public API usage”, so now before requesting a check, you need to make a request to check if the check exists.

    UPD According to Actie , in response to this question on the toaster , at the end of 2018, the Federal Tax Service released the official Check Verification API. “Access to the API is given if you write a statement, attest with an electronic signature, tell why and how you will use it.” (C)

    Documentation for receiving a token

    It is impossible to get a token to an individual, as far as I understand. Only legal person or individual. Also, when writing an application, you must explicitly indicate from which IP addresses you will request information on checks.
    The same user (organization (?)) - Actie implemented a gem for Ruby. But again, I note that using it without a token will not work. Link to the repository .
    The same repository states that with a large number of checks the API described in this article does not work stably. Personally, I did not check.

    Read Next