Към съдържанието

Ръководства

Баланс

Наличността, историята на движенията и данъчните документи четете през API и през MCP. Плащането с карта - еднократно и автоматично - винаги минава през връзка към Stripe Checkout, която завършва човек; API никога не тегли карта само. Същото важи и за незадължителния месечен план.

Пари без ДДС, стотинки, език на описанията

Всички суми в това API са цели числа в СТОТИНКИ (1/100 от чешката крона, hellers) и без ДДС - volai е регистрирано по ДДС, но ДДС се изчислява едва при зареждане на баланса с карта (преглед в /cenik). Описанията на движенията (GET /v1/credit/ledger) API съставя на английски от вида на движението - запазената чешка бележка никога не излиза навън, нито в друго поле.

Наличност, издръжливост и известия

GET /v1/balance връща текущата наличност плюс две допълнителни изчисления АДИТИВНО (съществуващите клиенти, които четат само balanceHal/balanceCzk/currency, не се чупят): runway (dailyAverageHal - средният дневен разход от последно време, runwayDays - за колко дни балансът стига при това темпо, null, когато не може да се изчисли) и notice - същото известие, което виждате на /prehled в портала, null, когато няма такова. Осем възможни вида на notice: {kind:"unknown"} (недостатъчно данни за оценка), {kind:"empty"} (нулева наличност), {kind:"number_fee",feeHal,dueAt} (до 3 дни е дължима месечна такса за гласови или мобилни номера и наличността не стига за нея; feeHal е сборът от всички такива такси, dueAt най-ранният падеж; не се връща при включено автоматично зареждане), {kind:"runway",days} (балансът свършва след days дни при сегашното темпо) и четири вида само за профил с месечен план: {kind:"subscription_exhausted_topup",renewsAt} (месечният баланс за този период е изчерпан и планът работи в режим на допълване, по-нататъшните разходи се плащат от зареден баланс; renewsAt е краят на периода в ms, когато се добавя нов месечен баланс), {kind:"subscription_cap_reached",renewsAt} (месечният баланс е изчерпан, планът работи с таван и зареденият баланс не покрива нищо, платените действия спират до renewsAt или до ръчно зареждане) и {kind:"subscription_past_due"} (подновяването на плана не мина, запазената карта не можа да бъде таксувана; подновяването платете в портала или сменете картата) и {kind:"subscription_runway",renewsAt,runsOutAt} (наличността свършва, преди в renewsAt да се добави нов месечен баланс; runsOutAt е оценка в ms кога ще свърши, от предпазливото темпо на плана, същото като прогнозата за месечния баланс на картата на плана в портала: най-високото от средното за 28 дни (само при пълна история на баланса), средното на оборота за последните 7 пражки дни без такси за номера и средното от началото на периода (едва след първата му седмица); runway продължава да смята със средното за 28 дни; абонатът го получава вместо runway, а при включено автоматично зареждане не го получава). renewsAt е в ms (epoch), т.е. същият момент като subscription.periodEnd в същия отговор, където е ISO 8601 низ; форматът на нито едно от двете полета не се променя. При план, отменен в края на периода, subscription_exhausted_topup, subscription_cap_reached и subscription_runway носят допълнително cancelAtPeriodEnd: true: подновяване няма да има, renewsAt е краят на плана и нов месечен баланс няма да се добави (при тавана тогава можете да продължите само със зареждане); без отмяна полето в известието го няма. При профил с месечен план отговорът носи допълнително subscription (състояние на плана, иначе null) и topupBalanceHal (само зареден баланс); balanceHal остава сборът от месечния и заредения баланс, вижте глава Месечен план.

История на движенията

GET /v1/credit/ledger?limit - най-новите движения първи, БЕЗ курсор (само limit, 1-200, по подразбиране 50) - по-стари движения от най-новите 200 през API не достигате, пълната история има порталът /kredit и данъчните документи. Всеки запис носи type (bonus, topup, call_out, call_in, sms, number_fee, agent, refund, admin, setup_revision - кръг корекции на поръчка Под ключ извън пакета, subscription_grant - добавяне на месечния баланс от плана и subscription_expire - изтичане на неизползвания му остатък), amountHal (положително е добавяне, отрицателно е приспадане), grossHal (сумата с ДДС при зареждане с карта, иначе null) и английско description, съставено от вида - при number_fee допълнително с номера, за който се отнася таксата. При разходи, покрити от месечния баланс, има допълнително поле fromSubscriptionHal - частта от разхода, покрита от месечния баланс; при останалите движения липсва. Добавката мобилен номер се показва в историята като number_fee (първият период при покупката и всяко подновяване след 30 дни) и sms (изпращане от мобилния номер, тарифата за сегмент е в ценовата листа); когато операторът впоследствие отхвърли SMS от мобилен номер, балансът се връща със запис refund.

Зареждане с карта

POST /v1/credit/topup {amountCzk} връща {checkoutUrl} - връзка към Stripe Checkout, която отваря ЧОВЕК в браузъра. Нищо не се тегли, докато той сам не завърши плащането. Адресът за фактуриране (PUT /v1/account/billing) трябва да е пълен ПРЕДИ извикването - без него не може да се издаде валиден данъчен документ (billing_address_required). Поддържа Idempotency-Key - безопасно е да се повтори след изтичане на времето, без да възникнат две плащания.

Автоматично зареждане

През API автоматичното зареждане може само да се ЧЕТЕ, ИЗКЛЮЧВА и да се променя ПРАГЪТ - включването и промяната на СУМАТА минават изключително през Stripe Checkout, никога чрез директен запис.

Защо не просто "enabled: true"

Когато картата вече е запазена, голото {"enabled": true} би задействало теглене БЕЗ ЧОВЕК при картата - точно това, което искаме да избегнем (спецификацията „Парите се движат само с човек при картата“). Затова PATCH /v1/credit/auto-topup отхвърля както enabled: true, така и amountHal със собствено съобщение, а не с обща грешка за неизвестно поле.

Четене и изключване

GET /v1/credit/auto-topup връща {enabled, thresholdHal, amountHal, card: {brand, last4} | null, spentThisMonthHal, monthlyCapHal, disabledReason} - БЕЗ номера на картата, само марката и последните четири цифри. PATCH {enabled: false} изключва веднага, PATCH {thresholdHal} променя само прага (трябва да е от предлаганата редица и по-нисък от запазената сума, иначе след зареждането наличността веднага пак пада под прага).

Включване и промяна на сумата

POST /v1/credit/auto-topup/setup {thresholdHal, amountHal} връща {checkoutUrl} - след завършване на Checkout ВЕДНАГА се тегли amountHal като първо зареждане и едва с това се запазва картата за бъдещи автоматични зареждания. Работи и с карта, запазена отпреди - това е единственият начин да включите автоматичното зареждане или да му смените сумата. След завършване на Checkout браузърът се връща на ЧЕШКАТА страница на портала (/kredit?automat=zapnuto) дори при англоговорящ клиент - позната празнина, не грешка във Вашата интеграция.

Карта

POST /v1/credit/auto-topup/card връща връзка към Checkout (режим на смяна на карта, нищо не се тегли) за смяна на запазената карта. DELETE /v1/credit/auto-topup/card отделя картата ВЕДНАГА - изтрива се цялата конфигурация (праг и сума), не само картата; следващо включване е възможно само отново през .../setup, който веднага тегли първото зареждане. След завършване на Checkout браузърът се връща на ЧЕШКАТА страница на портала (/kredit?karta=zmenena) независимо от езика на профила - същата позната празнина като по-горе.

Тавани

Два НЕЗАВИСИМИ тавана: най-много 10 000 CZK добавен баланс на календарен месец и най-много 4 зареждания на КАЛЕНДАРЕН ДЕН - независимо колко пъти наличността падне под прага. Надвишаването на който и да е от тях изключва автоматичното зареждане само (disabledReason monthly_cap, съответно daily_cap); spentThisMonthHal/monthlyCapHal в отговора показват колко остава от месечния таван.

MCP: get_auto_topup (четене) и disable_auto_topup (изключване) - включване, промяна на сумата и карта в MCP няма, по същата причина като enabled: true в REST по-горе.

Месечен таван на разходите

Незадължителна предпазна мярка срещу неочаквано висока сметка: сами определяте колко може да струват обажданията, SMS и гласовият агент за календарен месец (по пражско време). Функцията е включена само при профил, който си е задал таван; без него нищо не се променя, а разходът за месеца само се отчита.

GET /v1/account/spend-cap връща {spendCap: {enabled, capHal, warnShare, inboundAboveCap, month, monthSpendHal, remainingHal, reached, updatedAt}}. Без таван enabled е false и полетата на тавана са null, а monthSpendHal получавате винаги. Сумите са в цели стотинки без ДДС.

PUT /v1/account/spend-cap {capHal, warnShare?, inboundAboveCap?} задава или променя тавана: capHal е в цели стотинки от 5 000 (50 CZK) до 100 000 000 (1 000 000 CZK), warnShare е делът от тавана от 0,5 до 0,99 (по подразбиране 0,8), при който идва предупредителен имейл, а inboundAboveCap: true оставя агентите да продължават да приемат входящи обаждания и над тавана (по подразбиране false, при промяна без полето важи запазената стойност). DELETE /v1/account/spend-cap премахва тавана; премахването на несъществуващ таван е в ред.

След достигане на тавана новите изходящи обаждания, позвънявания, тестови обаждания и SMS се отхвърлят с код spend_cap_reached (HTTP 402), нищо не се таксува и повторението не помага, докато месецът не свърши или не повишите или премахнете тавана. Входящо обаждане на агент приключва след едно изречение и не струва нищо, освен ако не е inboundAboveCap: true. Имейл идва при достигане на warnShare и при достигане на тавана, винаги най-много веднъж месечно.

Какво таванът НЕ спира: обаждания, които текат в момента (цената се изважда едва след обаждането, затова месецът може да завърши над тавана с тяхната цена, както и при обаждания, осчетоводени след полунощ), пренасочване без агент и такси за номера, кръгът корекции Под ключ и месечният план, които не се броят към тавана. При профил с план в разхода се брои и това, което е покрил месечният баланс. Номер във Вашата SIP централа с inboundAboveCap: true остава в SIP проксито, така че таванът не спира изходящите обаждания от централата.

MCP: get_spend_cap, set_spend_cap и clear_spend_cap извикват същата услуга като REST и порталът (раздел Месечен таван на разходите в Баланс). set_spend_cap трябва да повтори на клиента сумата преди записа и след него.

Месечен план

Незадължителен абонамент: всеки месец от запазената карта се тегли цената на избраното ниво и се добавя месечен баланс в CZK, който се харчи по обичайната ценова листа. Тарифите и таксуването по секунди не се променят, планът е слой над тях. Нивата са три, а tier е тяхната цена в CZK без ДДС: "490", "990" и "1990"; цените и баланса на всяко ниво връща GET /v1/subscription в полето tiers.

Когато офертата не е достъпна

Офертата за месечен план може оперативно да се изключи за всички профили или само за някои. Когато е изключена за Вашия профил, GET /v1/subscription връща available: false, а включването завършва с грешка pausal_unavailable (404). Вече включеният план продължава да работи, дори офертата да бъде изключена.

Два вида баланс

Месечният баланс идва от плана, в края на периода изтича и е невъзстановим. Зареденият баланс (зареждане, приветствен бонус, корекции) не изтича и е възстановим както досега. Наличността на профила - balanceHal в GET /v1/balance, в портала и във всички прагове (минимум за обаждане, лимит на дълга, предупреждения) - е сборът от двата вида. Самостоятелно зареденият баланс е в topupBalanceHal, оставащият месечен баланс в subscription.monthlyRemainingHal. Дълг може да възникне само в заредения баланс.

Ред на разходите

Всеки разход минава първо през месечния баланс, а остатъкът през заредения - обаждания по секунди, агент, такси за номера и мобилните номера, SMS, позвънявания и изходящи задачи. Разделянето е атомарно и записано в дневника: разход, покрит от месечния баланс, носи fromSubscriptionHal (частта, покрита от месечния баланс). Корекциите на собственика (admin, и отрицателни) и връщането за неизпратена SMS (refund) засягат само заредения баланс.

Период и добавяне

Периодът е един месец от успешното теглене (31. 1. дава 28. 2.). Месечният баланс се добавя едва след потвърдено плащане със запис subscription_grant, а добавянето е идемпотентно по ID на плащането. Ако профилът в този момент има дълг в заредения баланс, той се погасява първо от новия месечен баланс, за да не остане зареденият баланс отрицателен.

Изтичане

Неизползваният остатък от месечния баланс изтича в деня на подновяване (запис subscription_expire с отрицателна сума), при приключване на абонамента или с автоматична предпазна мярка, когато периодът е свършил преди повече от 36 часа без подновяване. Ако тегленето не мине, остатъкът вече е изтекъл и нов баланс не се добавя; до плащането профилът работи само със заредения баланс.

Избор след изчерпване

При включване задължително се избира exhaustionMode, без предварителна стойност. topup: след изчерпване на месечния баланс от запазената карта се допълва зареден баланс - това е днешното автоматично зареждане със същите лимити и имейли. cap (таван): нищо не се допълва, изходящи обаждания, SMS и покупки на номера се отхвърлят с грешка subscription_cap_reached (HTTP 402), а когато балансът падне под нулата, спират и входящите обаждания, пренасочването и достъпът през SIP (спиране при нула; възобновява се след зареждане или с новия месечен баланс). С таван не може да се включи автоматично зареждане (subscription_cap_active); превключването към таван го изключва. Най-многото, което плащате за месец с таван, е цената на плана.

Смяна на ниво, отмяна, възстановяване

Смяната на ниво (нагоре и надолу) важи от следващия период, без доплащане. Отмяната е cancelAtPeriodEnd: true: балансът важи до края на периода, после изтича и състоянието е canceled; до края на периода отмяната може да се върне. През REST и MCP не може да се повиши нивото, да се възстанови отменен план или да се премине към допълване от картата - тези стъпки увеличават или отново включват повтарящото се теглене, затова връщат subscription_confirmation_required с confirmUrl, който човек отваря и потвърждава в портала (важи 24 часа).

Съвет преди подновяване

Три дни преди подновяването (най-късно ден по-рано) идва имейл, но само когато при досегашните разходи би Ви излязло по-евтино да плащате по секунди или с по-ниско ниво. Важи същото правило като при съвета в имейла за подновяване и в портала: другият път трябва да излиза поне с 50 CZK и 5 % по-евтино. Оценката за целия период взема по-високото от темповете от началото на периода и за последните 7 дни и никога не е по-ниска от разхода за последните 30 дни, от който съветва порталът; редовете Ниво и Отмяна затова след щракване не казват, че нивото е подходящо. Имейлът посочва точната дата и час на подновяване и идва най-много веднъж на период, никога при план, отменен в края на периода, с планирана смяна на ниво, без запазена карта или в очакване на плащане. Бутонът в него отваря в портала директно реда Отмяна (/kredit?pausal=zrusit) или Ниво (/kredit?pausal=stupen). Имейлът за подновяване после съветва отново от действителния разход за целия период, така че съветът може да излезе и различен.

Неплатено подновяване

Тегленето от запазената карта се опитва в деня на подновяване, след 2 и след 4 дни. След първия неуспех състоянието е past_due, идва имейл с връзка за ръчно плащане и за смяна на картата, а месечният баланс е 0; ръчното плащане връща POST /v1/subscription/pay. След третия неуспех планът приключва (canceled), зареденият баланс и профилът продължават да работят.

ДДС и документи

Цените са без ДДС. Режимът на ДДС се чете преди всяко теглене, така че платец от друга държава от ЕС с проверен данъчен номер плаща без чешки ДДС (reverse charge) и документът го отразява. Данъчен документ за всеки платен период издава самото volai (данъчната основа е цената на нивото, не добавеният баланс) и ще го намерите в GET /v1/billing/documents.

Връзка с бонуса и първото зареждане

Включването на плана се брои като първо плащане: отключва SMS от споделен изпращач, пренасочване, втори номер, мобилен номер и картата за автоматично зареждане по същия начин като зареждането. Приветственият бонус остава зареден баланс.

Възстановимост

Месечният баланс е невъзстановим и изтича; зареденият баланс е възстановим както досега. Отмяната на плана не поражда право на пропорционална част от платения период. Възстановяване на плащане за план (рекламация, грешка) урежда собственикът на volai ръчно, през API и MCP не е възможно.

Планът в REST и MCP

Парите се движат само с човек при картата. Включването на плана и ръчното плащане връщат само връзка към Stripe Checkout и никога не теглят картата директно; повишаването на ниво, възстановяването на план, зададен за край на периода, и превключването към допълване от картата изискват потвърждение от влезлия човек в портала.

  • GET /v1/subscription - състояние на плана (subscription или null), каталог на нивата tiers (id, priceHal, creditHal), topupBalanceHal, available (може да се включи нов план: офертата е включена и никакъв план не тече), recommendation (най-евтиният път за разхода за последните 30 дни и steady, дали разходът е траен, а не еднократен пик; null без оферта или без 30 дни история) и previousPeriod (минал период със същите числа като имейла за подновяване: usedHal от creditHal, usedPercent, разход над месечния баланс overHal и изтекъл остатък expiredHal; само при активен план, null в първия период и когато разходът не може да се докаже от историята).
  • POST /v1/subscription/checkout {tier, exhaustionMode, consumerConsent?} - връща {checkoutUrl} към Stripe Checkout, след чието завършване планът започва. exhaustionMode (topup или cap) е задължителен; потребител без фирмен номер трябва да изпрати consumerConsent: true (иначе consumer_consent_required). Адресът за фактуриране трябва да е пълен (billing_address_required). Поддържа Idempotency-Key.
  • PATCH /v1/subscription {tier?, cancelAtPeriodEnd?, exhaustionMode?} - намаляване на нивото, отмяна (cancelAtPeriodEnd: true) и превключване към таван (exhaustionMode: "cap") се изпълняват и връщат {subscription}. Повишаване на ниво, възстановяване на план, зададен за край на периода (cancelAtPeriodEnd: false), и exhaustionMode: "topup" нищо не променят и връщат 409 subscription_confirmation_required с confirmUrl.
  • POST /v1/subscription/pay - само в състояние past_due; връща {checkoutUrl} за ръчно плащане на подновяването. Поддържа Idempotency-Key.
  • POST /v1/subscription/card - връща {checkoutUrl} за смяна на запазената карта на плана, нищо не се тегли. Поддържа Idempotency-Key.
  • GET /v1/balance носи допълнително subscription (същият вид като по-горе, иначе null) и topupBalanceHal.

MCP: get_subscription (четене), create_subscription_link (връзка за включване), update_subscription и cancel_subscription (намаляване на ниво, отмяна, таван; повишаване, възстановяване и допълване връщат confirmUrl с изречение, че трябва да го потвърди човек в портала) и create_subscription_payment_link (ръчно плащане). Смяна на карта в MCP няма, по същата причина като при автоматичното зареждане: оттук нищо не се тегли.

Данъчни документи

Документът възниква автоматично при зареждане на баланса с карта (еднократно и автоматично), при плащане на настройка Под ключ и като коригиращ документ при връщане на настройката - никаква ръчна стъпка, никакво издаване през API.

GET /v1/billing/documents?limit&before - най-новите първи, курсорът before (Unix ms, изключителен) е nextBefore от предишната страница. Хранилището само никога не връща повече от 100 записа на едно извикване, дори limit да изисква повече.

GET /v1/billing/documents/{id} връща {id, number, issuedAt, taxableAt, netHal, vatHal, grossHal, vatRatePercent, reverseCharge, description, customer, paymentRef, pdfUrl} - reverseCharge: true при платци от друга държава от ЕС с проверен данъчен номер (VIES), които плащат без чешки ДДС. Полето kind е винаги попълнено - "invoice" при обикновен документ (и при документи, издадени преди въвеждането на полето), "credit_note" при коригиращ данъчен документ - той възниква автоматично, когато собственикът върне цената на настройката при отменена поръчка Под ключ, номерира се със собствена серия OD... и носи допълнително correctsNumber (номер на коригирания документ) и correctionReason (причина за връщането); сумите netHal/vatHal/grossHal са ПОЛОЖИТЕЛНИ и при кредитното известие, знакът минус добавя едва PDF.

GET /v1/billing/documents/{id}/pdf изтегля същия документ като application/pdf - генерира се наново при всяко изтегляне, не се съхранява. Чужд или несъществуващ id дава същата грешка (invoice_not_found) и в двете крайни точки, за да не може от отговора да се познае, че чужд документ съществува.

MCP: list_billing_documents и get_billing_document имат същия вид като REST. PDF има само в REST - MCP няма двоичен канал за пренос на файл.

Грешки

  • ledger_unavailable - В момента не успяваме да прочетем историята на движенията и наличността - опитайте отново след малко.
  • invalid_amount - Сумата за зареждане, прага или автоматичното плащане не е една от предлаганите фиксирани стойности.
  • billing_address_required - Адресът за фактуриране липсва или е непълен - допълнете го в портала (/nastaveni) преди зареждането, иначе не може да се издаде валиден документ.
  • stripe_not_configured - Плащанията са изключени за тази работна среда на volai - не се отнася конкретно до Вашата заявка.
  • stripe_error - Stripe отказа да създаде платежна сесия - опитайте отново след малко.
  • autotopup_not_configured - Автоматичното зареждане никога не е минавало през .../setup - няма какво да се изключи, промени, нито коя карта да се смени.
  • invoice_not_found - Документ с това id в профила няма (или принадлежи на друг профил - отговорът е същият).
  • spend_cap_reached - Месечният таван на разходите, който сте си задали, е достигнат: новите изходящи обаждания и SMS се отхвърлят и нищо не се таксува. Тавана повишавате или премахвате през PUT или DELETE /v1/account/spend-cap, иначе важи до края на месеца (до полунощ в Прага).
  • subscription_cap_reached - Таван на плана: месечният и зареденият баланс са изчерпани и профилът има избран таван. Изходящи обаждания, SMS и покупки на номера се отхвърлят (HTTP 402) до следващото подновяване или до ръчно зареждане.
  • subscription_exists - Профилът вече има план; смяната на ниво, отмяната и изборът след изчерпване минават през PATCH /v1/subscription.
  • subscription_missing - Профилът няма активен план, който да може да се променя, отменя или плаща ръчно.
  • subscription_canceled - Планът вече е приключил (състояние canceled): не може да се променя, отменя или плаща ръчно. Нов включвате през POST /v1/subscription/checkout.
  • subscription_confirmation_required - Повишаване на ниво, възстановяване на план, зададен за край на периода, и допълване от картата потвърждава само човек в портала - отговорът носи confirmUrl и нищо не е променено.
  • consumer_consent_required - Потребител без фирмен номер трябва при включване да потвърди изричното искане за започване на изпълнението преди изтичане на срока за отказ (consumerConsent: true).
  • pausal_unavailable - Офертата за месечен план е в момента изключена за този профил.
  • invalid_tier - Ниво, което планът вече има, когато няма планирано друго (нивото, към което вече преминава, не е грешка и се приема за изпълнено, така че същото PATCH /v1/subscription може да се изпрати отново след срив; изключение е връщането към днешното ниво, което отменя планираната промяна: при повторение вече няма какво да се отменя); непозната стойност извън "490", "990", "1990" завършва като validation.
  • subscription_cap_active - С таван не може да се включи автоматично зареждане; първо превключете избора след изчерпване на topup в портала.
  • validation - При PATCH /v1/credit/auto-topup конкретно: опит за включване (enabled: true) или за директна промяна на amountHal - използвайте вместо това POST .../setup.

Пълната таблица с грешки за всяка крайна точка ще намерите в раздела Баланс в справката за REST API.