Skip to main content
A message can cross the gateway four ways. They are genuinely different code paths and they fail differently, so being able to drive each on its own is what turns “something is wrong” into a bisection.

Setting up a lane

That creates an account with credit, a product with whitelisting off, an SMPP login and an HTTP login, a flat tariff, and the routing rules the four directions need. It is idempotent, and a matching teardown script removes exactly what it added.
Change the two passwords before pointing anything at this that is not your own machine.

Read the match order before you send anything

The router takes the first rule that matches, and the last rule matches everything. Two things follow, and both have already bitten a real deployment:
A delivery receipt for a message whose sender was a numeric Indian address arrives with that number in to, once flag.reverseDlrSrcDst has swapped source and destination.Placed below a to matches ^91… rule, that receipt goes to a vendor instead of to the customer.That is why the seed moves the destination rules down rather than just slotting a class rule in above the catch-all.
It falls to the catch-all, reaches the vendor worker, and is submitted upstream as a brand new outbound message.conf/routingTable.conf has always carried this rule. The database did not — and in database mode the database wins.
Both failures are silent from the customer’s side: in the first the receipt simply never arrives, in the second it arrives at a carrier as traffic you pay for. Neither produces an error anywhere.

What each direction proves

1

Direction 1 first — MT out over SMPP

If this fails, nothing else will work either. It covers the longest path.
2

Direction 2 — the REST ingress

Failing here while 1 works isolates the problem to the HTTP ingress: auth, parsing, rate limits.
3

Direction 3 — receipts back

The one most often broken by routing order rather than by the receipt path itself.
4

Direction 4 — MO in

Needs the destination number mapped to an account. An unmapped message is recorded and delivered nowhere, with nothing observable on the customer’s side.

Reading the outcome

Do not judge a lane by whether the send returned 200 — that only means accepted for routing. Check:
  • cdr_submit for a row, and cdr_final for an outcome
  • cdr_rejected for anything refused, with its reason
  • /ops/health for submitted moving on the vendor
  • The log for message.accepted, message.submitted, message.dlr

Throughput

A measured baseline to compare a load run against.

First checks

When a lane does not work.