> ## 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.

# STIR/SHAKEN attestation on Orbit voice

> How Orbit attests your outbound calls (A/B/C), how inbound attestation is parsed and enforced, and the controls you own — delegate certificates, branded calling, CNAM, and attestation policy.

# STIR/SHAKEN attestation

STIR/SHAKEN is the caller-ID authentication framework the FCC mandates for US
voice traffic. Every outbound call you place through Orbit is assigned an
**attestation level (A, B, or C)**, and every inbound PSTN call arriving at
your numbers carries an attestation result you can read and enforce policy
against. This page explains what the levels mean, where signing happens, and
which levers you control.

## What the attestation levels mean

The attestation level (ATIS-1000074) states two things: whether the
originating provider authenticated the customer, and whether it verified that
customer's right to use the calling number.

| Level | Name    | What it asserts                                                                          | How Orbit reaches it                                                                                                                                  |
| ----- | ------- | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| **A** | Full    | The customer is authenticated **and** their right to use the number is provider-verified | The caller ID is a number your organization owns through Orbit (purchased, active, billed to your org)                                                |
| **B** | Partial | The customer is authenticated, but number authorization is **not** provider-verified     | The caller ID is a leased pool number with an active assignment to your org, **or** a number covered by an active delegate certificate you registered |
| **C** | Gateway | The provider knows where the call entered the network but cannot verify the caller       | The caller ID cannot be attributed to your org, or the platform default fallback number is used                                                       |

Downstream carriers treat these very differently. A- and B-attested calls are
eligible for "caller verified" treatment; C-attested calls are the ones
carriers routinely label "Spam Likely." Field data across the industry shows
answer rates on A-attested traffic run dramatically higher than on C-attested
traffic — attestation level is the single biggest caller-identity lever you
have.

<Note>
  A delegate certificate raises a number you don't own on Orbit from C to
  **B only** — never to A. Orbit does not cryptographically validate the
  certificate chain or bind coverage to its real TNAuthList, so number
  authorization is not provider-verified. Full (A) attestation stays reserved
  for numbers owned through Orbit. This ceiling is deliberate: treating a
  self-registered artifact as A would let anyone spoof full attestation for
  arbitrary numbers.
</Note>

## Signing vs. signalling: who does what

Orbit never signs a PASSporT itself. The split of responsibility is:

1. **Orbit computes the level.** On every outbound call — API-initiated calls,
   dialer campaigns, transfers, conference dial-out, verification calls —
   Orbit resolves the caller ID against your ownership and lease records and
   any delegate certificates you registered, producing A, B, or C.
2. **Orbit signals the level.** The resolved level travels on the outbound
   INVITE as the custom `X-Devotel-Attest: <A|B|C>` SIP header.
3. **Devotel's wholesale softswitch signs.** Every outbound leg terminates on
   the carrier-of-record softswitch Devotel operates. It holds the
   STIR/SHAKEN signing certificate, reads the signalled level, and cryptographically
   signs the PASSporT at that level — it will never sign higher than what the
   platform attests.

Because signing happens on the Devotel-operated network, the call arrives
authenticated on the downstream carriers and mobile operators that actually
deliver it, instead of defaulting to an anonymous untrusted label.

If the ownership lookups behind level resolution fail (a database error, an
unresolvable caller ID), resolution fails open to C rather than blocking the
call — a signalled-downgrade is recoverable in your reporting, a blocked call
is not.

## Reading attestation on inbound calls

Inbound PSTN calls arrive with attestation signalling from the upstream
carrier, and Orbit parses it on the routing path. Two forms are recognized:

* **Pre-verified results (the common case).** Devotel's softswitch verifies
  the PASSporT signature upstream and forwards the result as an RFC 8588
  `Verstat` / `P-Attestation-Indicator` value (`TN-Validation-Passed-A/B/C`,
  `TN-Validation-Failed`, `No-TN-Validation`). This is the state for roughly
  all PSTN inbound traffic.
* **Raw `Identity` header.** When no pre-verified result is present, Orbit
  decodes the PASSporT payload and surfaces the claimed attestation level —
  flagged as not yet verified.

The parsed result is stored on the call record and rendered per call in the
dashboard:

| Result        | Meaning                                                                                                                       |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `A`, `B`, `C` | Signed and verified at that level (or claimed, pending verification)                                                          |
| `failed`      | A signature was present but verification failed — treat as spoof-risk                                                         |
| `none`        | The upstream explicitly reported no validation available                                                                      |
| `unknown`     | No attestation signalling at all — normal for off-net, SIP-trunk test, or LAN-originated calls; not a fraud signal on its own |

You can also set a **minimum attestation policy per DID** that rejects inbound
calls below a floor — for example, accept only A and B, or accept any signed
call. With no policy set (the default), every call is admitted. Rejected
calls receive a SIP 603 Decline.

## Tenant attestation policy

Beyond the per-DID inbound floor, Orbit keeps an **org-level attestation
policy**: a declared target level for your outbound traffic plus the inbound
verification floor your fraud posture is measured against. Three endpoints
cover it:

| Endpoint                                     | What it does                                                                                                                                                                                                          |
| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /api/v1/compliance/attestation/policy`  | Reads your org's policy. Always returns 200 — an org that has never set a policy gets the safe default posture below                                                                                                  |
| `PUT /api/v1/compliance/attestation/policy`  | Sets or patches the policy (owner/admin role required). Absent fields keep their current value, so you can update just the target without touching the rest                                                           |
| `GET /api/v1/compliance/attestation/posture` | Returns a posture snapshot: the applied attestation level for each of your originating numbers measured against your target, plus an inbound verification summary for the last 30 days classified against your policy |

### The policy fields

| Field                      | Values               | Default   | What it means                                                                                                                                                  |
| -------------------------- | -------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `target_attestation`       | `A`, `B`, `C`        | `A`       | The minimum attestation level you intend your outbound numbers to reach                                                                                        |
| `downgrade_handling`       | `monitor`, `alert`   | `monitor` | How reporting should treat numbers that attest below your target — `monitor` records them silently, `alert` marks them for surfacing to your team              |
| `inbound_min_verification` | `any`, `A`, `B`, `C` | `B`       | The inbound signing floor you treat as verified for fraud posture — `any` counts any signed level (A/B/C) as verified; `A`/`B`/`C` require at least that level |
| `flag_unverified_inbound`  | `true`, `false`      | `true`    | When true, inbound calls whose signature **failed** verification or arrived **unsigned** (`none`) are classified as spoof-risk rather than merely unverified   |
| `updated_at`               | ISO-8601 timestamp   | `null`    | Set on every write; `null` when the policy has never been explicitly set and the defaults apply                                                                |

A write is a patch: `PUT` with `{ "target_attestation": "A" }` alone leaves
your downgrade handling and inbound floor untouched. Invalid values return
`422 VALIDATION_ERROR`, and every successful write lands in your audit log.

### What the policy does — and does not do

**The policy is reporting and intent, not a gate.** Setting a target level
declares the posture you operate under and drives how posture and analytics
classify your traffic. It does not raise what gets signed, reroute a call, or
block one at dial time. Every outbound call still exits the Devotel wholesale
softswitch, which signs at exactly the level Orbit attests — it cannot and
will not sign higher than the attested level. If you set target `A` while your
traffic runs on leased pool numbers (B), nothing about call handling changes;
your posture snapshot simply starts reporting those numbers as below target
until ownership catches up.

```bash theme={null}
curl -X PUT "https://api.orbit.devotel.io/api/v1/compliance/attestation/policy" \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target_attestation": "A",
    "downgrade_handling": "alert",
    "inbound_min_verification": "B",
    "flag_unverified_inbound": true
  }'
```

The response returns the full policy as stored — merged with your existing
values for any field you omitted.

### Reading the posture snapshot

`GET /compliance/attestation/posture` answers two questions at once: which of
your originating numbers meet your target, and how inbound verification looks
against your floor.

```json theme={null}
{
  "data": {
    "policy": {
      "target_attestation": "A",
      "downgrade_handling": "alert",
      "inbound_min_verification": "B",
      "flag_unverified_inbound": true,
      "updated_at": "2026-08-20T14:03:11.000Z"
    },
    "originating": {
      "summary": {
        "total": 12,
        "meeting_target": 9,
        "below_target": 3,
        "by_level": { "A": 9, "B": 3, "C": 0 }
      },
      "numbers": [
        {
          "phone_number": "+14155550100",
          "source": "owned",
          "attestation": "A",
          "meets_target": true
        },
        {
          "phone_number": "+14155550777",
          "source": "leased",
          "attestation": "B",
          "meets_target": false
        }
      ],
      "numbers_truncated": false
    },
    "inbound": {
      "window_days": 30,
      "window_start": "2026-07-27T10:15:00.000Z",
      "window_end": "2026-08-26T10:15:00.000Z",
      "summary": {
        "total": 1840,
        "verified": 1712,
        "unverified": 96,
        "spoof_risk": 32,
        "verified_rate": 0.9304
      }
    }
  }
}
```

How to read it:

* **`originating.numbers[]`** lists each of your originating numbers with the
  level calls from it actually attest at: `owned` (a number your org owns
  through Orbit) → A, `leased` (an active pool assignment) → B. A number you
  hold neither way is never listed. `meets_target` compares that applied level
  against your `target_attestation`, and `originating.summary` aggregates the
  same into `meeting_target` / `below_target` counts. The list caps at 500
  numbers (`numbers_truncated` tells you when you hit the cap).
* **`inbound.summary`** classifies the inbound calls that arrived on your DIDs
  over the trailing 30-day window: signed calls at or above your
  `inbound_min_verification` floor count as `verified`; signed-but-below-floor
  and off-net (`unknown`) calls count as `unverified`; `failed` and unsigned
  (`none`) calls count as `spoof_risk` when `flag_unverified_inbound` is on,
  otherwise they fall into `unverified`. `verified_rate` is the verified share
  of all inbound calls, or `null` (not zero) when there was no inbound traffic
  in the window — so you can tell "no calls" apart from "0% verified."

Both reads are scoped to your organization: originating numbers come from your
owned numbers and active pool assignments only, and the inbound summary counts
calls that arrived on a DID currently assigned to your org. Because a released
DID that lands with a new owner records a fresh assignment time, a reassigned
number's inbound history starts clean — you never inherit the prior owner's
verification summary.

### Raising from B to A is an ownership play, not a PUT

If your posture shows leased pool numbers stuck at B against an A target, the
fix is number ownership, not policy change:

1. Purchase or port the numbers into Orbit so your org owns them outright.
2. Move your outbound traffic onto the owned DIDs.
3. Re-read the posture snapshot — those numbers now resolve to A and
   `meeting_target` closes the gap.

A `PUT /attestation/policy` can only restate your target and floors; no policy
value raises the level a number signs at.

## What you control

Attestation posture is **your setting, not Orbit's**. The controls you own:

* **Number ownership (highest-leverage).** Owning a number through Orbit is
  the only path to A attestation. If your answer rates matter, run your
  traffic from owned DIDs rather than pool or external caller IDs.
* **Delegate certificates.** If you legitimately control numbers you don't own
  on Orbit — verified external caller IDs, hosted or bring-your-own numbers —
  register the ATIS-1000092 delegate certificate you obtained from your
  service provider. Active certificates raise those numbers from C to B.
  Revoke a certificate and its numbers fall back to their ownership-based
  level immediately.
* **Attestation policy.** Set your org's target attestation level, how
  below-target downgrades are handled in reporting (monitor or alert), the
  inbound verification floor treated as verified, and whether unsigned
  inbound calls are flagged as spoof-risk.
* **Branded calling (Rich Call Data).** On A-attested calls, registered US
  carriers can render your verified brand name, logo, and reason-for-call on
  the recipient's handset (ATIS-1000095). Orbit passes your brand assets to
  the softswitch, which matches them against your per-carrier registration.
  Carriers without RCD support fall back to plain attestation plus CNAM.
* **CNAM pairing.** Register the calling name carriers display alongside your
  number. CNAM and attestation work together: attestation proves the number,
  CNAM names it.

<Warning>
  These are tenant-owned controls. Orbit records and enforces the policy you
  set; it does not mandate a posture for you, and regulatory compliance for
  your traffic remains your responsibility.
</Warning>

## Limits to be aware of

* **On-net vs. downstream.** Devotel signs every outbound call on-net, at the
  level Orbit signals. What downstream carriers do with that signature —
  displaying "caller verified", rendering RCD, or applying their own spam
  analytics — is outside Orbit's control and varies by carrier and handset.
* **A is ownership-only.** No configuration raises a non-owned number to A.
  Delegate certificates cap at B by design.
* **RCD is carrier-dependent.** Branded calling renders only on carriers
  where your brand registration is complete; elsewhere the call still carries
  full attestation, just without the rich display.
* **Inbound raw Identity is unverified.** When only a raw Identity header is
  present, the level is the caller's claim, not a cryptographically verified
  result — the pre-verified Verstat path covers the overwhelming majority of
  PSTN inbound.
* **Certificates are not chain-validated.** Registering a delegate certificate
  stores the authorization artifact you provisioned out-of-band; Orbit checks
  its status and validity window, not its cryptographic chain.

## Responding to ITG traceback requests

Signing your outbound traffic with STIR/SHAKEN attestation carries one
downstream obligation: when one of your originating numbers is implicated
in a robocall complaint, the **Industry Traceback Group (ITG)** — operated
by USTelecom under the FCC's TRACED Act framework — sends the originator a
**traceback request**. The request asks you to identify the upstream source
of the implicated traffic and file a disposition, typically within one
business day. Not responding is itself a compliance red flag: repeat
silence escalates toward FCC enforcement and carrier de-peering.

Orbit records the full lifecycle of each traceback request as a case on
your organization — intake, acknowledgement, disposition, deadline verdict
— so the evidence trail lives where your compliance team works. Log a
request the moment the ITG reaches you; the deadline clock starts at
intake.

| Endpoint                                            | What it does                                                                                                                                                                                                                                                                         |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `GET /api/v1/compliance/traceback`                  | Lists every traceback case for your organization, newest first, each annotated with a live SLA verdict                                                                                                                                                                               |
| `POST /api/v1/compliance/traceback`                 | Logs a new inbound ITG traceback request (owner/admin role required): supply `traceback_ref` (the ITG's reference), `source_number` (the implicated originating number, E.164), and optionally `campaign_description`, `attestation`, `notes`, and `sla_hours` (default 24, max 720) |
| `GET /api/v1/compliance/traceback/:id`              | Fetches a single case with its current SLA verdict                                                                                                                                                                                                                                   |
| `POST /api/v1/compliance/traceback/:id/acknowledge` | Records that you acknowledged receipt to the ITG; you may add `notes` (owner/admin role required)                                                                                                                                                                                    |
| `POST /api/v1/compliance/traceback/:id/respond`     | Files your disposition — `source_identified`, `customer_notified`, `customer_terminated`, `number_disabled`, `not_originated_here`, or `no_action`, plus optional `notes`; pass `close: true` to close the case in the same call (owner/admin role required)                         |

```bash theme={null}
# 1. Log the traceback request as soon as it arrives
curl -X POST "https://api.orbit.devotel.io/api/v1/compliance/traceback" \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "traceback_ref": "ITG-2026-04117",
    "source_number": "+14155551234",
    "campaign_description": "Warranty robocall complaint against this originating number"
  }'

# 2. Acknowledge receipt to the ITG
curl -X POST "https://api.orbit.devotel.io/api/v1/compliance/traceback/$CASE_ID/acknowledge" \
  -H "Authorization: Bearer $ORBIT_API_KEY"

# 3. File your disposition and close the case
curl -X POST "https://api.orbit.devotel.io/api/v1/compliance/traceback/$CASE_ID/respond" \
  -H "Authorization: Bearer $ORBIT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "disposition": "number_disabled", "close": true }'
```

Cases move one-directionally through
`received → acknowledged → responded → closed`. Attempting a transition a
case has already passed — responding to a closed case, acknowledging a
responded one — returns `409 TRACEBACK_INVALID_TRANSITION`.

### How the SLA verdict is computed

Every case carries a live deadline verdict, recomputed on each read, not
cached. The deadline is `received_at + sla_hours`; the window defaults to
24 hours (the ITG's customary one-business-day window) and you can
override it per case up to 720 hours when a request states a different
deadline. The verdict is one of:

| Verdict    | When                                                                          |
| ---------- | ----------------------------------------------------------------------------- |
| `met`      | You responded on or before the deadline                                       |
| `breached` | The deadline passed with no response on file, **or** the response landed late |
| `due_soon` | The case is open with four hours or fewer left                                |
| `on_track` | The case is open with time to spare                                           |
| `unknown`  | The intake timestamp is missing or invalid, so no deadline can be evaluated   |

The case payload returns the verdict alongside `due_at`,
`hours_remaining`, and a `breached` flag. In audit terms a breach means:
every intake, acknowledgement, and response is written to your audit log,
and a breached case sits there as documented evidence you missed the ITG
window — the record regulators and carriers ask for first when a complaint
escalates.

### Your posture, Orbit's ledger

Responding to a traceback is your decision and your filing. Orbit's role
is the ledger: it records the request, your acknowledgement, and your
disposition with timestamps, and it computes the deadline verdict. Filing
a response never places a call, sends a message, or reconfigures a carrier
— it updates the case record, nothing more. Regulatory compliance for your
traffic — including responding to the ITG in substance — remains your
responsibility; Orbit gives you the record to do it on.

<Note>
  Cases are stored on your organization's settings under
  `itg_traceback_cases`, each persisted as its own entry — logging a new
  request or updating one case never rewrites or blocks the others, so
  parallel intake from several complaints at once is safe.
</Note>

## Deep dives

* [Voice channel overview](/channels/voice) — carrier-of-record architecture
* [CNAM & caller ID](/numbers/cnam) — register and dispatch calling names
* [Voice data residency & retention](/compliance/voice-data-residency) — where attested call data lives
* Attestation API — delegate certificates, attestation policy, and posture snapshots under [Compliance endpoints](/api-reference/endpoints/compliance)
* ITG traceback workflow — the [traceback case endpoints](#responding-to-itg-traceback-requests) above, plus the full schema in the [Compliance endpoints reference](/api-reference/endpoints/compliance)
