SMS API for Malaysia

Send from your own application — OTP, order updates, reminders — over a REST API built so that a network timeout on your side cannot charge you twice.

What you would use it for

The part most SMS APIs get wrong

Your HTTP client has a timeout. Ours has a network. Sooner or later your request will time out after we created the message but before you got the response — and your retry logic will send it again. Without protection that is a double charge and two SMS to every recipient, and neither is refundable because the operator already billed for both.

Every send accepts an Idempotency-Key header. Retry the same request as many times as you like: the first call does the work, every later call returns the identical response including the same message ID, and nothing is charged twice.

curl https://hantarsms.com/api/v1/messages \
  -H "X-API-Key: $HANTARSMS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-48213-reminder" \
  -d '{"to":["60123456789"],"text":"Your order #48213 is ready for pickup."}'

Delivery reports, per number

Totals are not much use when a campaign underperforms. The API returns the outcome for each individual number, and it distinguishes two states that many providers collapse into one:

StatusMeaningCharged
deliveredOperator confirmed handset receiptYes
undeliveredAccepted by operator, never reached the handsetYes
rejectedNever submitted — invalid number or blocked contentNo, refunded
sentSubmitted, final receipt not in yetYes

Merging rejected into undelivered makes your invoice impossible to reconcile, because one is billable and the other is not.

What else is in it

Full reference

Endpoints, parameters, every error code and working examples in PHP, Python, Node.js and Java are in the API documentation. It is readable without an account — worth a look before you register, to confirm it fits how your system is built.

Frequently asked questions

Is there a monthly fee for API access?

No. The API costs the same per segment as sending from the web console, with no platform fee, no minimum volume and no separate API plan. You pay for messages.

What happens if my request times out and I retry?

If you sent an Idempotency-Key header, nothing — the retry returns the original response and the same message ID, and you are charged once. Without that header a retry is treated as a new message, so send the header on every request.

Can I use the API to send OTP?

Yes, and that is one of the main uses. Messages go out from a shared 5-digit short code, which is the sender format users expect for one-time passwords. See short code SMS.

How do I get delivery status back?

Poll the message endpoint for a summary, or the recipients endpoint for the per-number breakdown. Status is refreshed from the operator when you read it. Webhook push is on the roadmap; polling is the supported method today.

Which languages do you have examples for?

The documentation has complete working examples in curl, PHP, Python, Node.js and Java. It is a plain REST API with JSON, so any HTTP client works — there is no SDK to install.

Get an API key in two minutes

Register, generate a key from the console, send a test to your own phone on trial credit.