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

# Honeypot trap DIDs and the caller-reputation feed

> Register, arm, and retire unlisted trap numbers; read the inbound trap-hit log and the per-caller spoofing and robocall reputation feed it produces, and wire that signal into your own inbound routing and do-not-originate posture.

# Honeypot trap DIDs and the caller-reputation feed

A **honeypot** (also called a trap or seed number) is an owned DID that is
deliberately never published — not on a website, not in an ad, not listed in
a lead list. Because a legitimate caller has no reason to reach that number,
**every inbound hit on it is suspicious**, and repeat hits are a strong
robocall or spoofing fingerprint. The honeypot program turns that trickle of
suspicious inbound traffic into a per-caller reputation feed you can act on.

This guide covers the operator surface for the program: registering trap
numbers, reading the trap-hit log, reading the caller-reputation feed, and
wiring that signal into the inbound routing and do-not-originate controls
you already own. The surface is **super-admin only** — trap numbers are
cross-tenant security infrastructure, not a per-tenant feature.

<Note>
  Compliance framing: this program is posture and signal only. The reputation
  feed is an input to your routing and do-not-originate posture — Orbit does
  not mandate how you act on it. Nothing below is legal advice.
</Note>

## 1. Why a trap number is inbound-only

Trap numbers receive; they never originate. In Orbit's routing table for
[inbound numbers](/guides/inbound-number-routing), a honeypot DID is exactly
the case the `decline` action exists for: answer with SIP 603, take the hit
into the log, and terminate the call with no media path and no per-call
billing. Registering a number as a trap never wires it for outbound voice or
SMS — inbound termination only. That is also why trap hits are safe to
aggregate: every hit is, by construction, inbound traffic you never
solicited.

## 2. Registering a trap DID

Pick the number first. The four categories tell an operator what kind of
trap it is — pick one and keep it accurate, because the category is the only
context the hit log carries about why a number is suspicious:

| Category           | Meaning                                                                                                                        |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| `aged_unallocated` | A number acquired from a carrier range and left unlisted long enough that residual legitimate traffic has died down.           |
| `recycled`         | A number previously assigned to someone else, now returned to the pool — the hits tell you who is still calling the old owner. |
| `seeded_list`      | A number deliberately planted in a purchasable list — the hits tell you which list is actually used for dialing.               |
| `partner_supplied` | A number provided by a partner network exchange or a carrier penetration program.                                              |

Register the trap; `organization_id` is optional — omit it to make the trap
platform-owned, which is what you want for a global suspicious-number feed:

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/admin/honeypots" \
  -H "Authorization: Bearer $ORBIT_ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "+14155550123",
    "trap_category": "aged_unallocated",
    "label": "NYC trap DID"
  }'
```

The `phone_number` must be E.164 and the registry is unique per number —
re-registering an already-registered number returns a 409 telling you it is
on the list. Wrong category or a typo in the label is fixable later (Step 3).

List the registry and filter by state, category, owning org, or search text:

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/admin/honeypots?active=true&trap_category=aged_unallocated&limit=100&offset=0" \
  -H "Authorization: Bearer $ORBIT_ADMIN_API_KEY"
```

## 3. Retire, re-arm, and relabel a trap

A trap that is temporarily leaked into a legitimate context (a corporate
directory, a carrier test page) starts producing noisy hits. Retiring it
(`active: false`) stops its hits from feeding the reputation scorer while
keeping the registry entry and the historical hits for audit. When the noise
settles, re-arm it from the same call. Everything that can change on a trap
lives in one PATCH:

```bash theme={null}
curl -X PATCH "https://api.orbit.devotel.io/api/v1/admin/honeypots/honeypotDid_01H8..." \
  -H "Authorization: Bearer $ORBIT_ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "active": false }'

curl -X PATCH "https://api.orbit.devotel.io/api/v1/admin/honeypots/honeypotDid_01H8..." \
  -H "Authorization: Bearer $ORBIT_ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "active": true, "label": "NYC trap DID — re-armed" }'
```

Only hits landing on a **currently active** trap feed the scorer — a retired
trap is read-only history, never score data. Both the register and the
update land in the audit log under the `security.honeypot.register` /
`security.honeypot.update` actions so follow-up review can rebuild who
armed what.

## 4. Reading the trap-hit log

The raw log is one row per call or SMS that landed on a trap, newest first.
Filter by trap, caller number, channel, or time window:

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/admin/honeypots/hits?caller_number=+12125550199&channel=voice&from=2026-09-01T00:00:00Z&to=2026-09-20T00:00:00Z&limit=100" \
  -H "Authorization: Bearer $ORBIT_ADMIN_API_KEY"
```

```json theme={null}
{
  "data": {
    "hits": [
      {
        "id": "hpHit_01H",
        "honeypot_did_id": "hpDid_01H",
        "trap_number": "+14155550123",
        "caller_number": "+12125540199",
        "channel": "voice",
        "attestation": "C",
        "source_ip": "203.0.113.44",
        "reference_id": null,
        "hit_at": "2026-09-18T13:42:11Z"
      }
    ]
  },
  "meta": { "request_id": "req_01H", "timestamp": "2026-09-20T08:16:00Z" }
}
```

The four fields worth reading first:

* **`caller_number`** — the originating ANI. Unlike tenant-facing call logs,
  this is the actionable fraud signal (a suspected robocaller), so the
  verbatim number is available to the operator.
* **`attestation`** — the first-hop STIR/SHAKEN level on the inbound leg:
  `A` (full), `B` (partial), `C` (gateway — origin not verified), or
  `unsigned` (no signature). Repeat `C` / `unsigned` hits against traps are
  the classic spoof pattern.
* **`source_ip`** / **`reference_id`** — the hop the inbound gateway saw,
  when it can be attributed; use it to correlate with your webhook logs.
* **`hit_at`** — the precise timestamp for time-window pulls.

## 5. Reading the caller-reputation feed

The scorer rolls recent trap hits into one row per caller number, worst
first. Ask for the whole feed, or filter to one band:

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/admin/honeypots/reputation?sample=2000&limit=100&offset=0" \
  -H "Authorization: Bearer $ORBIT_ADMIN_API_KEY"

curl "https://api.orbit.devotel.io/api/v1/admin/honeypots/reputation?band=high_risk" \
  -H "Authorization: Bearer $ORBIT_ADMIN_API_KEY"
```

Each row carries a caller number, its score (0–100, higher is worse), its
band, its total hits, its distinct-trap count, its low-attestation hit
count, and a human-readable reason list. Bands run `clean < suspect <
high_risk < blocked` — any single hit already lands a caller in `suspect`,
and only a clear abuser pattern reaches `blocked`. The scoring is
deterministic; the inputs that raise the score are volume (repeat hits),
range-scan (the caller touching many distinct trap DIDs — the strongest
robocall fingerprint), and unsigned / C-attestation hits.

```json theme={null}
{
  "data": {
    "reputations": [
      {
        "caller_number": "+12125540199",
        "score": 73,
        "band": "high_risk",
        "hit_count": 6,
        "distinct_traps": 3,
        "low_attestation_hits": 6,
        "reasons": [
          "hit a honeypot trap DID (6 hit(s))",
          "repeat-hit volume (+15)",
          "scanned 3 distinct trap DIDs (+16)",
          "unsigned STIR/SHAKEN on trap hit (+15)"
        ]
      }
    ],
    "hits_scored": 1874,
    "caller_count": 91,
    "sampled": true
  },
  "meta": { "request_id": "req_01H", "timestamp": "2026-09-20T08:16:00Z" }
}
```

`sampled: true` means the window covered the full `sample` hits (default
2000, max 5000) — the worst callers are still worst, but a `sampled` read
may miss the tail. Page with `offset`/`limit` exactly as on the registry and
the hit log: the scorer always runs over the full window so band ordering is
stable across pages.

## 6. Wiring the signal into your tenant posture

The trap-hit log and the reputation feed are **inputs**, not actions. Three
tenant-owned places to use them, in order of how common the wiring is:

1. **Inbound routing.** A caller that ranks `high_risk` on the reputation
   feed is a candidate for the `decline` (SIP 603) action on your inbound
   numbers, or for routing into a recording-only queue instead of your
   agents. See
   [Inbound number routing](/guides/inbound-number-routing) for how the
   `decline` action works and why it is the cheapest answer.
2. **Do-not-originate.** The same feed is a candidate source for your DNO
   list — a caller that keeps hitting honeypots is also a caller that
   probably spoofs other numbers on outbound. Do **not** auto-populate the
   DNO list: catch it in the feed, review the hit pattern, and only then
   add the caller to the list. See
   [Do-Not-Originate (DNO) Caller-ID Blocking](/compliance/do-not-originate).
3. **Fraud review.** A suspicious inbound caller pattern is also an alert
   you should triage in the [Fraud Shield](/guides/compliance-fraud-shield)
   ledger when it lands over one of your own DIDs — the honeypot feed follows
   the caller, your own DIDs follow the tenant-side evidence.

Either way, the decision — block, decline, list — is yours. The trap program
exists to surface the signal; the posture is the tenant's.

## Related references

* [Do-Not-Originate (DNO) Caller-ID Blocking](/compliance/do-not-originate) —
  the tenant-owned control the reputation feed feeds into.
* [Inbound number routing](/guides/inbound-number-routing) — the `decline`
  action that trap hits and high-risk callers are routed to.
* [Work a Fraud Shield alert end to end](/guides/compliance-fraud-shield) —
  triage the alerts your own inbound traffic raises, using the honeypot feed
  as corroborating evidence.
* [ITG traceback workflow in the dashboard](/guides/compliance-traceback-itg) —
  the traceback cases that one-call-lookup trap hits become evidence for.
* [STIR/SHAKEN attestation](/channels/voice/stir-shaken) — what the
  attestation level on a hit means.
