NUACOM API

Billing

Top Up

Top-ups add prepaid credit to the account by charging one of its saved cards. There are three kinds: balance, the money that pays for calls (and, on pre-pay accounts, for messages); call credit, the older name of the same balance; and SMS credits, bought in packages. Each kind has a one-off top-up, a calculate preview of the price with VAT, and an automatic top-up configuration that NUACOM charges when the balance drops to a limit. The cards come from Payments; the SMS packages and what the credits buy are in Conversations / SMS.

Workflow (what the portal does)

The portal's Balance Top Up page:

  1. Preview the price: POST /v2/top-up/balance/calculate with amount, an integer from 1 to 9999 in the account's billing currency (billing.billing_currency on the account info), answers {"amount": 20.0, "vat_rate": 0.23, "vat": 4.6, "total": 24.6}. vat_rate is the rate in force today for the account's VAT type (0 when none applies); vat and total are rounded to two decimals. The portal recalculates as the amount changes.
  2. Charge the card: POST /v2/top-up/balance with the same amount and payment_method, the id of one of the account's cards from GET /v2/payments. total is charged to the card at once, without the cardholder present, and the answer is 204 with no body. The balance is credited shortly after, when Stripe's confirmation reaches NUACOM, and a receipt is emailed to the account's billing address.
  3. Watch the balance: the portal polls the balance until it changes. Read billing.account_balance on GET /v2/account_info.
  4. Automatic top-up: GET /v2/top-up/auto/balance returns the configuration, or 204 when there is none. POST /v2/top-up/auto/balance with amount (1–9999), balance_limit (an integer of at least 1) and payment_method creates or replaces it and answers 204: whenever the balance is at or below balance_limit, NUACOM charges amount plus VAT to that card. DELETE /v2/top-up/auto/balance switches it off (204, also when nothing was configured).

The call credit endpoints, POST /v2/top-up/call/calculate, POST /v2/top-up/call and the GET, POST and DELETE /v2/top-up/auto/call configuration, take the same inputs (credit_limit in place of balance_limit), and a top-up through them credits the same balance; they are the older Call Credit Top Up page. Use the balance endpoints for new work.

The portal's SMS Top Up page:

  1. Pick a package: GET /v2/sms/packages lists them with id, amount of credits and cost, at the account's own prices where NUACOM has agreed some.
  2. Preview: POST /v2/top-up/sms/calculate with package_id quotes the package's cost as amount, with vat_rate, vat and total.
  3. Charge: POST /v2/top-up/sms with package_id and payment_method charges total to the card (204). The credits are added when the confirmation arrives and show in billing.sms_balance on the account info; they stay valid for one year from the purchase.
  4. Automatic top-up: GET, POST /v2/top-up/auto/sms (package_id, credit_limit, payment_method) and DELETE /v2/top-up/auto/sms store an SMS configuration. Read Pitfalls before relying on it.
curl -X POST https://api.api-nuacom.com/v2/top-up/balance \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"amount": 20, "payment_method": "pm_1AbCdEfGhIjKlMnOpQrStUvW"}'

Reading a configuration

An automatic top-up configuration carries id, account_id, user_id (the admin who saved it), payment_type (2 for a Stripe card, 1 for a card held with NUACOM's earlier card records), payment_method (the pm_… id, or the legacy card reference), amount on the balance and call kinds or package_id on the SMS kind, balance_limit or credit_limit, and set_time, when it was last saved.

How the automatic top-up runs

flowchart TD
    trigger["Call ends, or SMS/MMS/WhatsApp message sent (scheduled or bulk included)"] --> compare{"balance <= balance_limit?"}
    compare -- "no" --> skip["No charge"]
    compare -- "yes" --> charge["Charge amount + VAT to saved card"]
    charge -- "success" --> credited["Balance credited"]
    charge -- "card reports no longer usable" --> removed["Configuration removed at once"]
    charge -- "declined" --> retry1["Retry 1, 5 minutes later<br/>billing address emailed"]
    retry1 -- "success" --> credited
    retry1 -- "declined" --> retry2["Retry 2, 5 minutes later"]
    retry2 -- "success" --> credited
    retry2 -- "declined" --> removed
  • It runs after a call ends and after an SMS, MMS or WhatsApp message is sent, scheduled and bulk sends included. It reads the balance configuration, compares the account balance with balance_limit and, at or below it, charges amount plus VAT to the saved card without the cardholder present. One attempt runs at a time.
  • A declined card is retried twice, five minutes apart. The billing address is emailed about the failure (a card that needs 3-D Secure gets an email asking to authenticate it). After the third failure the configuration is removed, and saving it again is what re-enables it. A card that Stripe reports as no longer usable is not retried: the configuration is removed at the first failure.

Roles and access

  • Every endpoint in this group needs an account admin: the user behind the token must be an admin of the account, or the answer is 403 with the body "Forbidden".
  • The API does not look at the account's billing type: it accepts a top-up from a bill-pay account as readily as from a pre-pay one. Which pages the portal shows is the portal's decision.
  • The ISO dates option (per account) switches set_time to ISO 8601 in the requested timezone.

Pitfalls

  • 204 means the card was charged, not that the balance has moved. The credit lands when Stripe's confirmation arrives, shortly after; poll the account info rather than repeating the top-up.
  • Two payment failures answer 400 with an error_code: PAYMENT-DECLINED (message carries the card provider's reason) and PAYMENT-INCOMPLETE (the payment needs the cardholder; incomplete_payment.client_secret identifies it, and the portal completes it with Stripe.js in the browser). Nothing is credited until the payment succeeds; a completed PAYMENT-INCOMPLETE payment is credited through the same confirmation. See Errors.
  • payment_method must be one of the account's cards, else 422 with errors.payment_method "Payment method does not exists". The three auto save endpoints also accept a saved card reference from an earlier card record, but the automatic top-up this API runs charges Stripe cards only: save a pm_… id.
  • Only the balance configuration drives the automatic top-up that runs after calls and messages. The call and SMS configurations are stored and returned for the older portal pages, but no charge is made from them through this API.
  • amount is an integer: 20.50 is refused with 422, and 9999 is the maximum per top-up.
  • A card referenced by any of the three configurations cannot be deleted from Payments until the configuration points at another card.
  • GET /v2/top-up/auto/… answers 204, not 404 or null, when nothing is configured; DELETE answers 204 even then.
  • SMS credits expire one year after purchase.