> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshoot sender-ownership 422s (SENDER_NOT_OWNED)

> Decode the pre-send sender-ownership gate — `422 SENDER_NOT_OWNED` for a numeric E.164 sender another organization holds, and its fail-closed 503 sibling `SENDER_OWNERSHIP_CHECK_UNAVAILABLE` — and send from an identity you own in minutes.

# Troubleshoot sender-ownership 422s

Numeric senders pass through a hard pre-send ownership gate. When the
E.164 number you named in `from` belongs to a different organization on
the platform, the send is refused before it ever reaches a carrier — the
Devotel softswitch trusts the originator field, so without this fence a
recipient would see (and attribute the message to) the true owner's
number. The gate returns `422 SENDER_NOT_OWNED`, and when it cannot
confirm ownership because of a transient database or cache fault it
refuses the send with `503 SENDER_OWNERSHIP_CHECK_UNAVAILABLE` instead.
Both are pre-send rejects: no message is submitted and no message charge
is taken.

## Match the code to its meaning

| Code                                 | HTTP | What fired                                                                                                                                                        | Fix class                                            |
| ------------------------------------ | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| `SENDER_NOT_OWNED`                   | 422  | The numeric E.164 `from` is not in your organization's numbers **and** belongs to a different organization — direct assignment or an active platform-number lease | Change the sender to an identity you own             |
| `SENDER_OWNERSHIP_CHECK_UNAVAILABLE` | 503  | The ownership lookup itself failed (transient datastore/cache fault), so the gate failed **closed** and refused the send rather than pass it                      | Retry after a short backoff; no sender change needed |

The distinction drives the fix: `SENDER_NOT_OWNED` is a sender fix —
retrying the identical payload returns the same 422 forever. The 503
sibling is a transient platform state — retry the same request after a
short backoff (about 30 seconds, with jitter).

`SENDER_NOT_OWNED` fires only on cross-organization collisions. Sending
from a fully custom number that your organization does not own and that
no other organization holds produces a different flow. The deliberate
trigger list:

* Cross-org number — hard reject.
* Stale tenant number — your org once held the number, then released it
  and another organization claimed it. Released inventory stays
  selectable in older dashboards or hard-coded apps, so sends from it
  start failing here.
* Softphone direct number — an extension's assigned caller ID that is no
  longer in your inventory is rejected on the same code when an agent
  texts from that extension.

## Fix the 422 — pick a sender you own

The gate accepts any sender identity your organization legitimately
controls. Apply one of these once, then retry the send:

1. **Send from a number you own.** List active inventory with
   `GET /api/v1/numbers` and pass one of those E.164 numbers in `from`.
   A number you purchased or ported in passes with no extra step.
2. **Verify an external number through the register → confirm flow.**
   If your own handset or landline must appear as the sender, enrol it
   once and the gate accepts it afterwards:
   * Register — `POST /api/v1/voice/caller-ids/verify` with the E.164
     `phone_number` and the `channel` (`"sms"` or `"voice"`). Orbit
     sends a one-time code to that handset (a text on SMS, spoken
     readback on voice).
   * Confirm — `POST /api/v1/voice/caller-ids/confirm` with the
     `verification_id` and the code. A correct code flips the row to
     `verified` and opens the number as an outbound sender.
   * A wrong code or an elapsed TTL leaves the row `expired`; re-arm it
     with `POST /api/v1/voice/caller-ids/:id/resend` and confirm again.
     The full endpoint contract is in
     [Manage outbound caller IDs](/guides/voice-caller-ids), and the same
     journey runs from the dashboard under **Voice → Caller IDs**.
3. **Use the platform default.** Omit `from` (or omit the pool) and the
   resolution chain falls back to the shared `(Devotel)` sender — see
   [Sender resolution](/concepts/sender-resolution). Alphanumeric sender
   IDs registered to your organization skip the numeric ownership lookup
   entirely, subject to destination-country alpha rules (US/Canada
   carriers reject alphanumeric senders outright — send to those
   destinations from a number).

Replacing a sender on an automated pipeline: update the one place that
supplies it — the campaign's sender field, the sender pool members, or
the extension's default caller ID — rather than editing every send body.

## Why the 503 fails closed

An ownership check that errors rather than answering has a choice: pass
the send along without an ownership verdict, or refuse it. The gate
refuses it. Passing along would let a momentary datastore or cache
outage quietly disable the only control that stops one organization
from sending under another organization's number — recipients would see
the wrong number, and carrier complaints would land on the true owner.
A brief 503 that a retry clears is cheaper than that, so the gate
treats "cannot confirm ownership" the same as "ownership denied": the
send is refused until the check works again.

If 503s persist beyond a few minutes: check
[status.orbit.devotel.io](https://status.orbit.devotel.io), then retry
through your normal idempotent retry path. The 503 is safe to retry —
the send was never submitted, and re-sending with the same idempotency
key cannot duplicate a message.

## Sample error envelopes to paste into a ticket

Cross-org numeric sender, `POST /api/v1/messages/sms`:

```json theme={null}
{
  "error": {
    "code": "SENDER_NOT_OWNED",
    "status": 422,
    "message": "Sender \"+12125550198\" is not registered to this organization. Choose one of your own phone numbers, the platform default (Devotel), or an approved alphanumeric sender ID.",
    "details": { "sender": "+12125550198", "channel": "sms" }
  }
}
```

Transient ownership-check failure (same request):

```json theme={null}
{
  "error": {
    "code": "SENDER_OWNERSHIP_CHECK_UNAVAILABLE",
    "status": 503,
    "message": "Sender ownership check for \"+12125550198\" is temporarily unavailable. Retry in a moment, or switch to the platform default (Devotel) sender / one of your registered phone numbers.",
    "details": { "sender": "+12125550198", "channel": "sms" }
  }
}
```

When you open a support ticket, paste the full `error` object, the
endpoint, and the timestamp — the `sender` and `channel` fields in
`details` are what support needs to trace the gate decision.

## Related references

* [Sender resolution](/concepts/sender-resolution) — the precedence
  chain that picks a sender when the request names none.
* [Troubleshoot sender resolution and pool errors](/troubleshooting/sender-resolution-errors) —
  the sibling codes `SENDER_REQUIRED`, `SENDER_POOL_NOT_FOUND`, and
  `NO_SENDER_CONFIGURED`.
* [Fix an empty sender pool](/troubleshooting/sender-pool-empty) — the
  pool 422 that resolves but has no members.
* [Manage outbound caller IDs](/guides/voice-caller-ids) — the
  register → confirm journey and lifecycle states.
* [Error codes](/reference/error-codes) — the full send-gate error
  table.
