SaffronSuite

Saffron SIP

iPhone not ringing? Every fix

Almost every 'it doesn't ring' has one of five causes, and the relay tells you which in its response. Test the wake path from a terminal first; the PBX is innocent until curl says otherwise.

Start here: the two-second test

Lock your phone. From any machine, send a fake wake with the values your app is really configured with:

terminal
curl -s -w "\n%{http_code}\n" https://sipreg.saffronsuite.com/v1/incoming-call \
  -H "Authorization: Bearer pk_your_key_from_the_app" \
  -H "Content-Type: application/json" \
  -d '{"call_id":"test-'$RANDOM'","to":"sip:101@pbx.example.com","from":"100","display_name":"Test"}'

Phone rings and you see 202: the wake path is healthy, skip to the PBX-side section. Otherwise, find your code below.

404 no_active_devices: the big one

The relay couldn't find an enrolled phone matching your to value. It matches exactly against what the app registered:

the matching rule
app Settings → Account            your webhook must send
Username:       101
Server Domain:  pbx.example.com   →   "to": "sip:101@pbx.example.com"
  • Different host: the app says pbx.example.com but the dialplan sends the internal IP (sip:101@10.0.0.5). Send the domain the app uses.
  • Bare extension: "to": "101" is rejected; it must be a full sip:user@host.
  • Case: the user part is case-sensitive; the host isn't.
  • Not enrolled yet: open the app once after setting up the account and check Settings → Incoming Calls shows it's registered with the relay.

401 invalid_api_key

The pk_ key is missing, mistyped, or was rotated. Re-copy it from Settings → Incoming Calls, and check the header is exactly Authorization: Bearer pk_…. If you rotated the key in the app, every PBX config that used the old one needs the new one.

402 subscription_required

The wake service needs an active subscription on the account (it's the one server we run; the app and your PBX do the rest for free). Subscribe or restore purchases in the app, then retry: no PBX changes needed.

422 invalid_payload

A field failed validation, and the response's issues array names it. Usual suspects: a malformed to, an over-length field, or broken JSON from unescaped quotes in a caller name. Keep payloads under 8 KB.

409 idempotency_conflict or previously_failed

Same call_id, different payload: retries must resend the identical body. previously_failed means that call already failed once; new call, new call_id.

502 apns_failed

The relay reached Apple but Apple couldn't deliver to any device. Usually transient; if it persists, the app may have been offloaded or reinstalled: open it once so it re-enrols a fresh push token.

The webhook works, but real calls don't ring

  • No wake fired: check the webhook actually runs in your dialplan (watch the Asterisk CLI while calling; the NoOp line from the guide should print).
  • Rings, then instantly stops: the INVITE went out before the app re-registered. Keep the Wait(1.5) between webhook and Dial.
  • Registration rejected: transport mismatch. The app defaults to TLS on 5061; if your PBX only speaks TCP or UDP, set the transport in the app under Settings → Advanced, or set up TLS properly.

It rings, but audio is one-way or missing

That's NAT, not the relay. On the endpoint make sure rtp_symmetric = yes, force_rport = yes, rewrite_contact = yes and direct_media = no, and that your firewall passes the RTP range (10000-20000/udp by default). If the PBX is behind NAT itself, set external_media_address on the transport.