API changelog
Changes to the public API and to how verification methods behave. Newest entries first.
2026-10-30
Changed
-
Russian method labels in the dictionaries.
pass_callis now "Голосовой код" instead of "Голосовое подтверждение",smsis "СМС",mts_idis "МТС ID",max_otpis "MAX — код" andmax_botis "MAX — бот". The values are unchanged — only the labels inGET /meta,GET /configandGET /meta/dictionaries/methodsmoved. -
VK ID and Яндекс ID sign-in prices in
GET /dashboard/prices. Aproviderslist now carries the charge per completed sign-in. It is deliberately absent fromGET /v1/prices: a provider sign-in cannot be requested throughPOST /v1/verify— it happens inside the hosted sign-in page and is enabled in the client's settings. Listing it publicly would advertise a method the API would refuse.A provider with no configured price is not listed — it is live and free.
Every methods item has a
description field — one sentence on what the method does. Enough to render a method picker
entirely from the API response, without keeping the copy on your side.
The old label didn't say the thing that matters: the user receives a code and has to type it.
In a list of methods that is the key distinction — reverse_flash_call verifies without a code,
pass_call with one.
2026-10-29
Added
-
Value dictionaries, so you don't keep your own copy.
GET /meta/dictionarieslists the dictionaries on offer andGET /meta/dictionaries/{name}returns one: values exactly as the API sends them, with labels in the language of the request (Accept-Language). No authentication required.Dictionaries are named after the fields they describe: an
operatorvalue resolves againstoperators, astatusagainststatuses. Responses are cached for an hour.Why: a label table living in frontend code drifts from the API silently — and breaks on exactly the values that were added most recently.
2026-10-28
Fixed
-
The pay-from-your-phone QR opens again. On the balance top-up page the code could fail to load and returned an error. It is now drawn on our side and is available for card, SBP and T-Pay top-ups.
SberPay has no QR: its link opens by tapping it on the same device, and a phone camera does not recognise it. The page keeps the payment button instead.
Changed
-
A new account opens after review. Signing up in the dashboard now creates the account in a pending-review state: dashboard access and API keys are available immediately, but
POST /v1/verifyand the other API methods answer401until the account is approved. This normally takes a business day — write to support@verificahub.ru if you need it sooner.Existing accounts are unaffected: review applies to new sign-ups only.
-
A
401now tells a wrong secret apart from a closed account. The two used to look identical, which sent people hunting for a credentials bug that did not exist. -
The "website" field accepts the main domain only.
https://your-company.comis fine,https://your-company.com/account/requestsis not, and neither is a URL carrying ad-tracking parameters. Enforced both at sign-up and when editing the profile.
Added
-
New method
pass_call— voice verification. A robot calls the number and dictates the code; the user types it intoPOST /v1/verify/check, as withsms. The code is never delivered as a message, so it cannot be read off a locked screen's notification.{ "phone_number": "+79161112233", "method": "pass_call" }Charged when the call is requested, not when it is answered: the carrier bills us for placing it regardless of whether anyone picks up. An unanswered call returns
failedwith the charge already made — unlike the reverse flash call, where you pay only for a successful verification.The call carries the caller-ID label "ИП Iskuzhin IT" — a legal requirement for calls from a legal entity, and your own service name cannot be substituted. Say so on your waiting screen: the user will see a call from a name they do not recognise.
Available on request. If the method is closed for your account,
POST /v1/verifyanswers 403 witherror_code: method_not_available. If the method is not wired on the platform at all, it answers 400 witherror_code: validation_error. Worth telling apart: the first is fixed by asking us, the second means nobody has it yet.
2026-10-27
Fixed
-
POST /v1/verifyno longer refuses verifications with402 no_gateway_availablebecause of a daily limit on our side. On high-volume days the built-in daily issuance budget could run out well before the day was over, and further requests were refused although the verification was deliverable. The limit is gone. Theno_gateway_availablecode stays — but it now means delivery genuinely cannot be carried out, not that today's allowance is spent.Retrying after this error is still worthwhile: the conditions that raise it are usually short-lived.
2026-10-22
Changed
-
GET /v1/pricesandGET /dashboard/prices: every method now carriesavailable. The tariff stays in the list with its price, andavailabletells you whether your account may use that method. An account with no restriction seestrueon every row.{"prices": [{ "method": "mts_id", "price": { "amount": 2.50, "currency": "RUB" }, "available": true },{ "method": "sms", "price": { "amount": 3.00, "currency": "RUB" }, "available": false }]}
Added
-
SMS now names your site and your account — as
max_otpalready did. The recipient can see whose code it is:1057 - Vash kod podtverzhdeniya na resurse partnyora https://example.ru (Primer)The name comes from your account profile, plus your legal entity when your requisites are filled in. The text stays Latin and still fits a single SMS, so the price of the method is unchanged.
-
New error code:
403method_not_available. Returned byPOST /v1/verifywhen the method is not available to your account right now;detailnames the methods that are. It is the same rule asavailablein the price list, so the list and what/v1/verifyaccepts never disagree. Methods you already have configured are unaffected — the restriction is set per account, not applied retroactively. -
method_policy.stepson phone-verification clients is checked when you save. A step naming a method your account may not use is refused with the same403method_not_availableon create and on edit, rather than silently dropping out of the ladder mid-flow.
2026-10-07
Added
-
max_otp— a new verification method: the code arrives as a MAX message. 2.00 ₽. Nothing to open — no link, no bot, no app: the message simply arrives, like an SMS. The user types the code intoPOST /v1/verify/check, as withsms.POST /v1/verify{ "method": "max_otp", "phone_number": "+79991234567" }The message carries your website and name, so the recipient can tell whose code it is:
2483 - ваш код подтверждения на ресурсе партнера https://example.ru (Пример (c) ООО «Пример»)The name comes from the account name, followed by the legal name from your requisites when they are filled in. Check in the dashboard that what is there is what you want shown to people.
Charged on send: delivery is synchronous, so the response comes back after it. A number that is not on MAX creates no verification and costs nothing —
422, as with any other undeliverable.max_botstays, and it is over six times cheaper — 0.30 ₽ against 2.00 ₽. They are two different methods, not one replacing the other: withmax_botthe user opens a bot from a link and shares their number, withmax_otpthey do nothing. Choosing between them trades price for that step. -
Number lookups — two new services. Separate from verification: a lookup does not prove anyone owns the number, it tells you about the number itself.
POST /v1/lookup/number-info— operator, region, and whether the number was ported. 0.80 ₽POST /v1/lookup/activity— how active the number is in the network, 0 to 1. 1.50 ₽
Both work on numbers from any RU operator. Every response carries
cost— exactly what was charged; reconcile against it."No data for this number" is an answer, not an error: it returns
200withstatus: "no_data", and we do not charge for it, nor for a number outside a service's operator coverage. Errors stay errors: malformed number (400), insufficient funds (402), service unavailable (503). -
Check a list of numbers from the dashboard. Upload a file of numbers (CSV, or simply one number per line) and get the results back as a file; up to 50,000 numbers at a time.
You choose the check — number activity or number info. The price is the same as for a single check; the speed is not: an activity list is computed in one go and comes back quickly, while number info is collected a number at a time, so a large list takes hours rather than minutes.
You pay for the numbers that came back with an answer. A number with no answer is not counted — the same rule as for a single check. The balance is checked before the job starts, so a job you cannot pay for is not half-run. A job that never completes costs nothing.
Repeats in the file count once. Lines that are not a checkable number are left out of the job and returned to you with their line numbers — including the file's header row.
The results stay downloadable for a limited time: the file holds your numbers, and we do not keep them longer than needed.
-
Lookup tariffs in
GET /v1/prices. Alookupslist now sits alongsideprices. They are two separate lists and should stay separate: a verification is charged at its own milestone (send, attempt or success, depending on the method), a lookup per answer. A service with no live tariff is not listed. -
Lookup usage in
GET /v1/usage. A newlookupsblock:"lookups": {"total": 40,"billable": 37,"total_cost": { "amount": 31.10, "currency": "RUB" },"by_method": { "number_info": 25, "activity_score": 15 },"by_status": { "ok": 37, "no_data": 3 }}The report's top-level fields are still verifications only — lookups are not included in them. Spend for the range is
total_cost+lookups.total_cost.billableis how many requests were charged for; it is belowtotalby exactly those with no data for the number. -
Lookup services in the reference data from
GET /metaandGET /config: a separatelookupslist, pluslookup_statusesandbulk_lookup_statusesin/config.
Changed
-
Number lookups are included in the акт and its detalization. They count towards the акт's amount alongside verifications, and the detalization gives them their own "Проверки номеров" sheet: a single lookup as a row with its masked number, a bulk job as one row naming the file and how many of its numbers were charged. The summary splits the total into verifications and number lookups.
Amounts on акты for past periods are not recalculated.
-
max_botis now labelled "MAX Bot" in the reference data, and "MAX" meansmax_otp. Both methods used to be shown as "MAX", which made it impossible to pick the right one by name. The values (max_otp,max_bot) are unchanged — only the labels inGET /metaandGET /configmoved.
Fixed
-
Activity checks answered
503instead of "no data". When a number has no activity score,POST /v1/lookup/activityreturned503 lookup_unavailable— "try again later" for a request whose answer will not change. It now returns what was promised:200withstatus: "no_data"andcostof 0.There is no point retrying: the operator has no activity score for that number. A number-info check on the same number may well answer — it is a property of the service, not of the number, so checking it with the other service is worth doing.
-
Bulk activity checks: the first number of the list was not checked, and numbers with no answer reached the invoice. The job looked complete, but its result was missing the first row, and the cost was computed from how many numbers were processed rather than how many answered.
You now pay only for numbers that came back with an answer — the same rule as a single check. A job shows both counts:
numbers_processedfor how many were worked through,numbers_billedfor how many were charged.Jobs that ran before the fix are worth running again: their result file is missing its first row. If one of them was charged more than it has answers for, tell us and we will refund the difference.
2026-10-02
Fixed
-
Invoice PDF download in the dashboard. The download button on a счёт returned an error and no file came through. Fixed — the invoice now downloads, and arrives with a meaningful name ("Счет № 3 от 29.09.26.pdf" instead of "invoice-3.pdf").
We also keep our own copy from the moment a счёт is issued, so it stays downloadable for 30 days regardless of how long the file link itself lasts. If you need an invoice for accounting beyond that, download and keep it within the window.
2026-10-01
Added
-
Credit limit: a permitted negative balance. For accounts where this is agreed in a contract, verifications keep working once the balance goes below zero, down to the agreed floor. Every other account behaves exactly as before: verifications stop at a zero balance.
GET /v1/balancegains two fields:credit_limit— how far below zero the balance may go, ornullif it may not;available— what is actually left to spend:balance+credit_limit.
Watch
available, notbalance. A request costing more thanavailableis refused withinsufficient_balance(402) — the error code has not changed. On an account with a credit limitbalancecan legitimately be negative, and that on its own is not an error.The low-balance email is now measured against remaining room rather than against zero, so a credited account is warned as it nears its floor instead of as its balance crosses zero.
2026-09-29
Added
-
Detalization alongside the monthly act. The monthly act is now accompanied by an
.xlsxbreakdown for the period — four sheets: summary, by verification method, by day, and a line-by-line list of billed verifications with date, masked number, method, status and amount. Download it in the dashboard; the link arrives with the act.Amounts come from what was actually charged, so the detalization total matches the act. Everything you were charged for is listed — including verifications that did not succeed: SMS is billed on send and Mobile ID per attempt, so billed rows with status "expired" or "failed" do appear, and that is expected. The summary calls those out on their own line, and a "by status" sheet breaks them down.
Verifications you were never charged for are not listed, but the summary shows how many there were so the period reads in full.
2026-09-26
Added
-
Why a verification failed.
GET /v1/verify/{request_id}and the dashboard verification list now returnfailure_reasonon unsuccessful verifications:no_response(nobody acted before it expired),declined(the subscriber refused),wrong_code(attempts exhausted),not_delivered(the code or call never arrived),unreachable(the number cannot be served by this method), orunknown. The set is fixed and safe to branch on, and the list endpoint can filter by it (?filter=failure_reason==not_delivered). -
Your own low-balance threshold.
PUT /dashboard/accountnow takeslow_balance_threshold— the balance at which we email the account owner. It was previously a single platform-wide figure (100 ₽) that could not be changed. Sendnullto follow the platform default, or0to switch the warning off. The response returns both your value and the threshold actually in force (effective_low_balance_threshold).
Fixed
- Repeat low-balance warnings. An account already below the threshold stopped receiving the email entirely, no matter how much further the balance fell. The warning now fires once on dropping below the threshold and re-arms after a top-up.
2026-09-24
Changed
- Only Russian mobile numbers are accepted.
POST /v1/verifynow answers400 region_not_supportedunless the number is a Russian mobile number (+79…). Previously any eleven digits starting with7were accepted, which let through Kazakh and Abkhazian numbers, Russian landlines, and typos such as8890…that normalisation turned into a plausible-looking+7890…. None of these can be delivered to, and none has ever verified — the request is now rejected outright, with no verification created and nothing charged.
2026-09-21
Fixed
mts_id, Tele2 and MegaFon subscribers. SMS-code confirmation failed and the verification expired even when the code was entered correctly. The method now works for subscribers of every operator.- Resubmitting an already-accepted code no longer costs an attempt. Once
the operator has accepted a code, a repeated
POST /v1/verify/checkreturns409 not_pendinginstead of400 invalid_code, and no attempt is spent. - The
verification.failedevent is now delivered to your webhook for themts_idmethod as well. Previously, running out of attempts on this method was only visible viaGET /v1/verify/{request_id}.
Note for integrators
- With
mts_id, a code is only ever entered on the SMS-OTP leg, which is used when SIM-push confirmation is unavailable. There is nothing to enter during SIM-push, andPOST /v1/verify/checkreturns409 not_pendingthere. - On the SMS-OTP leg, a
200means the operator accepted the code; the response body still reportssent. The outcome arrives as averification.verifiedevent (typically within a second), or viaGET /v1/verify/{request_id}.
Billing
- Verifications affected by technical issues on our side have been recalculated. Balances were credited and the affected integrators notified.