SMS

Pricing and limits

What each SMS, verification and number costs, read at runtime, and the sending limits that keep bulk marketing off the platform.

Pricing

Prices are set at runtime and can change without a release, so read them rather than hardcoding them. All amounts are CAD cents. Sending is billed per SMS part: message_cost_cents × the parts the carrier splits the body into. Parts are counted the way the carrier counts them: typographic quotes, dashes and ellipses are smart-encoded to GSM-7 (160 characters, then 153 per part), while emoji and most accented letters force Unicode parts (70, then 67). The charge is settled to the carrier's part count after the send. A message the carrier rejects outright costs nothing, and so does a send to a reserved exchange (555-XXXX and similar), which is refused here; a message the carrier accepts but cannot deliver keeps its charge. A body over 10 parts is refused with 422 MESSAGE_TOO_LONG before any charge. verification_cost_cents covers a typical single-part OTP; a long or non-GSM app_name can add a part. phone_number_activation_fee_cents is charged once, together with the first month, on every number provisioned, local or toll-free, and is not refunded on release. inbound_message_cost_cents is charged per part of every SMS received on a provisioned number, sender and carrier included, except STOP, START and HELP keywords; a received message is debited even if it takes the balance below zero, which pauses sending until the next top-up.

bash
# Current prices, in CAD cents
curl https://api.honkio.ca/v1/pricing \
  -H "Authorization: Bearer mk_live_YOUR_KEY"

# Response 200:
# {
#   "message_cost_cents": 3,
#   "verification_upcharge_cents": 25,
#   "verification_cost_cents": 28,
#   "phone_number_upfront_cost_cents": 250,
#   "phone_number_monthly_cost_cents": 250,
#   "phone_number_activation_fee_cents": 100,
#   "inbound_message_cost_cents": 3
# }

Test-mode requests are priced identically in the response but never charged, so you can see what an integration would cost before spending anything.

Sending limits

HonkIO is built for transactional and relationship messaging, not campaigns, and every customer’s deliverability rides on a shared carrier profile. These limits keep bulk marketing off the platform; a clinic, a contractor or a SaaS sending codes will not notice them. The sending limits apply to live mode only; the link-shortener rule, the reserved and undeliverable destination checks, and the broadcast group-size cap run in both modes.

  • Daily cap: new accounts can send 250 live messages per rolling 24 hours. It does not lift on its own. 30 days after your first live message you can request a higher volume from the dashboard; approval sets 1,000 a day or the figure you asked for. Refused sends return 429 DAILY_LIMIT_REACHED with your limit and count.
  • Identical messages: the same body may reach at most 250 distinct recipients per 24 hours (429 FANOUT_LIMIT_REACHED). Personalized messages are unaffected.
  • Per-number rate: 6 messages per minute per sending number, the most a Canadian carrier accepts from a 10-digit number (429 NUMBER_RATE_LIMITED with Retry-After).
  • Broadcasts: up to 250 recipients per contact-group broadcast and 3 broadcasts per 24 hours (422 BROADCAST_TOO_LARGE, 429 BROADCAST_LIMIT_REACHED).
  • Link shorteners (bit.ly, tinyurl and similar) are refused in both modes because carriers filter them (422 LINK_SHORTENER_BLOCKED). Use the full URL.
  • Delivery warning, then automatic pause: if more than 10% of your last 50 live messages fail at the carrier, you are emailed (and account.delivery_warning fires) without any pause. If more than 1% of recipients reply STOP, or more than 5% of messages are rejected by carriers, over your recent sends, live sending pauses for 24 hours and you are emailed (403 SENDING_PAUSED with the resume time; account.sending_paused fires).
  • Top-ups: the balance cannot exceed $500 and top-ups are limited to $1,000 per 30 days. Raised on request.
  • Per-recipient cap: 30 messages to one recipient per hour and 100 per 24 hours (429 RECIPIENT_RATE_LIMITED with Retry-After). A two-way conversation never gets near it; a script retrying one number does.
  • Undelivered messages are billed: a message the carrier accepts but cannot deliver keeps its charge. A reserved exchange (555-XXXX, N11 exchanges such as 411 or 911, carrier test codes, exchanges starting with 0 or 1) is refused for free with 422 RESERVED_DESTINATION, in test mode too, and a reserved area code (555, 911 and the like) as non-Canadian. Anything that retries should send an Idempotency-Key header so a retry can never become a second charge. An hour of unusual spend triggers an email and account.spend_warning.
  • Undeliverable numbers: after 3 consecutive carrier failures to one number within 30 days, from any HonkIO customer, sends to it are refused without charge (422 UNDELIVERABLE_NUMBER with the failure count, when it was listed and when it expires) for 90 days, then retried in case the number was reassigned.
  • Inbound cap: each account can receive at most 1,000 texts per rolling 24 hours by default (support can raise it). Texts past the cap are recorded without their content, not charged, and fire no message.received; the first one in a window sends account.inbound_sms_capped. STOP, START and HELP are always processed.
bash
curl https://api.honkio.ca/v1/send-limit \
  -H "Authorization: Bearer mk_live_YOUR_KEY"

# → { "daily_limit": 250, "sent_last_24h": 12, "remaining": 238,
#     "recipient_rate_per_hour": 30, "recipient_rate_per_day": 100,
#     "probation": { "ends_at": "2026-09-26T14:02:11.000Z", "eligible_to_request": false },
#     "paused_until": null, "requests": [] }

Read your current limits and usage with GET /v1/send-limit, and file a request with POST /v1/send-limit/requests. Every figure above is a platform default that can be raised per account.