Skip to main content
FireFlo’s REST API is deliberately close to Jasmin’s — same paths, same auth, same field spellings — so most integrations move with a one-line change.

The one breaking change

Jasmin answers with a string you pull a UUID out of. FireFlo answers with an object.
Jasmin
FireFlo
Errors are unchanged — {"message": "…"} at the same status codes.

Delivery receipts: close, not identical

Field names follow Jasmin’s, so a receiver reading id and stat works unchanged. Two differences:
FireFlo POSTs application/json. A receiver parsing application/x-www-form-urlencoded needs to read JSON instead.This is the change most likely to be missed, because the receiver keeps returning 200 while parsing nothing.
Jasmin sends one. FireFlo’s resolver is handed only the delivery state and never an error code, so emitting one would mean inventing it.stat still distinguishes UNDELIV, REJECTD and EXPIRED, which is the information that actually exists.
dlr-level follows Jasmin’s meaning — 1 the SMSC-level notification, 2 the terminal one, 3 both — and defaults to 2. Anything outside 1–3 is a 400.
dlr-method is accepted but does not choose the format. That is a gateway-side setting. If your Jasmin integration relied on it, ask your provider which format they forward, and note that the kannel format is a bare GET whose URL must carry %s/%d placeholders — without them the callback arrives completely empty.

Two behaviours that differ

sms_count is "ND" because credit is money, and how many messages it buys depends on where they are going. Rather than invent a number, the field says it is not determined. 402 is a new status to handle. It is deliberately not folded into 403, where it would be indistinguishable from a wrong password — but a client that treats every 4xx alike will retry it forever, which cannot help.

What you do not have to change

  • Every path: /ping, /secure/send, /secure/sendbatch, /secure/balance, /secure/rate. No version prefix.
  • HTTP Basic on /secure/*.
  • Underscore and hyphen spellings are interchangeable — with custom_tlvs keeping its underscore, as in Jasmin.
  • to may be a string or a number, and an array in a batch.
  • globals merged into every message, per-message values winning.
  • schedule_at in both "3600s" and "YYYY-MM-DD HH:MM:SS" forms.
  • callback_url / errback_url receiving batchId, to, status, statusText.
  • There is no batch status endpoint — in Jasmin or here.

Two things that are not carried over

Scheduled batches are not durable by default. Jasmin puts a Celery queue behind batches; FireFlo submits in process, and a broker is optional.If you rely on a scheduled batch surviving a gateway restart, confirm with your provider that they run RabbitMQ — and that they alert on amqp.bridge.degraded, because durability is silently lost while the broker connection is down.
No Celery and no broker requirement, which is a simplification everywhere except the line above.

A migration order that works

1

Change the messageId extraction

The one breaking change. Do it first; everything else still works while you do.
2

Switch your receipt handler to JSON

And confirm it by checking your own logs, not by checking that receipts return 200 — they will either way.
3

Add a 402 branch

Alert rather than retry.
4

Re-check anything reading sms_count

It is now always "ND".
5

Run both in parallel on a small share

Compare delivery rates knowing FireFlo reports the worst segment of a long message, so its numbers are legitimately lower than a gateway reporting the first.

API overview

The envelope, auth and field-name rules in full.

Delivery receipts

The payload FireFlo sends, field by field.