Carrier providers
Provider selection, normalized carrier signals, billing boundaries, failover settings and measured lookup health.
Availability and rollout
Carrier routing keeps each lookup within the account group you chose. The implementation is available in source; failover starts off. It runs only when the service global switch, your service-managed rollout flag and your saved failover preference are all enabled. Saving a preference cannot enable the service switches.
While any switch is off, existing single-provider lookups and ordinary JSON responses keep their previous behavior. A lookup with no provider uses your registered Vonage Identity Insights application first, then your registered Sinch project if Vonage is absent. This is account selection, not a retry after a provider failure.
Use Settings, Carrier routing to order providers, choose required capabilities and save the complete preference. Only organization administrators see this editor; the server authorizes each request separately. Refreshing health keeps an unsaved draft. If a save cannot be confirmed, reload the saved preference before saving again. Concurrent editors use full replacement, so coordinate changes with other administrators.
Providers and capabilities
| Wire name | Whose account | Dispatch capabilities | Limits |
|---|---|---|---|
| vonage_identity_insights | Your registered Vonage application | SIM swap | Application/operator approval applies. |
| sinch_number_lookup | Your registered Sinch project | Line type, porting; approved SIM swap | SIM swap requires project approval and a US or Canada number. |
| vonage | PasskeyBridge hosted add-on | Line type, porting | Number Insight does not report SIM swap. |
| twilio | PasskeyBridge hosted add-on | SIM swap, line type | Does not report porting or roaming. |
All selected required capabilities must be available on an adapter before it is attempted. No current provider implements device swap, so requiring it produces no eligible provider. Listing a provider means the integration exists; it does not prove an account is configured or approved. The providers action retains its older public capability names such as port_check; the preference field uses porting.
Zumigo is a disabled reserved adapter with no credentials, host or network calls. It is absent from the public providers list and cannot be selected in preferences. Replay is a separate staging test path and never enters automatic failover. See Carrier provider setup for account registration.
Failover and billing boundaries
With every rollout gate enabled, an explicitly named provider leads the attempt order, followed by the remaining preference entries. An unnamed lookup follows the preference order among your own accounts. Only configured, enabled providers with all required capabilities are eligible.
Tenant-owned Vonage and Sinch accounts can fail over to each other. A hosted request can use only hosted Vonage/Twilio accounts and first requires the hosted carrier lookups add-on. A failure never crosses between your accounts and the hosted billing group. Eligibility checks can skip a provider without a vendor call.
Only a failure marked retryable advances to the next eligible account. Timeout and temporary unavailable outcomes may be retryable; auth, invalid_number and unsupported stop. An unexpected adapter failure or unconfirmed failed-outcome telemetry also stops further spending. A successful signal remains usable if passive telemetry cannot be confirmed, with a fixed server monitoring-gap diagnostic.
Each actual attempt has its own 15-second outbound deadline. Open circuits are skipped with a circuit_open attempt and zero latency, without a lookup sample. There is no automatic application-level retry of the whole request. A repeated lookup can issue another billable provider request.
Normalized schema and version negotiation
The new schema is opt-in on the active failover path. Send Content-Type: application/vnd.passkeybridge.carrier.v1+json with the usual JSON request. Ordinary application/json returns the previous v0 signal fields even when failover is active. With failover disabled, the vendor media type does not force v1. The record path and every forward to shield-ingest keep their existing v0 shape.
The v1 signal adds schema_version: 1, sim_swap_window, line_type, observed_at and provider_latency_ms. It retains the normalized carrier fields and the server-keyed phone_hash; it never returns the number, personal name or raw provider body. The digest identifies equality within the platform privacy model and is not an anonymization claim.
sim_swap_window is <24h, <7d, <30d, none or unknown. No detected swap maps to none; a detected swap with no usable age maps to unknown. Ages at or beyond 30 days also map to none, so read sim_swap_detected as well. line_type mirrors carrier_type. observed_at is the adapter observation time, not proof of the operator's data freshness. provider_latency_ms measures the successful adapter; top-level latency_ms covers dispatch.
The active dispatch response adds attempts in order. Each entry has provider, a closed outcome and latency_ms. The attempt list also accompanies bounded dispatch failures. Missing or capability-ineligible accounts do not produce attempted lookup entries.
Example normalized response
This synthetic success illustrates a tenant-owned timeout followed by an eligible approved Sinch result. The values are examples, not a latency claim. The keyed digest stands in for a synthetic subject.
{
"status": "ok",
"signal": {
"schema_version": 1,
"provider": "sinch_number_lookup",
"phone_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"signal_type": "carrier_check",
"risk_score": 0,
"carrier_name": "Example network",
"carrier_type": "mobile",
"ported": false,
"reachable": true,
"roaming": false,
"sim_swap_detected": false,
"sim_swap_age_hours": null,
"sim_swap_window": "none",
"line_type": "mobile",
"observed_at": "2026-10-31T00:00:00.000Z",
"provider_latency_ms": 180
},
"latency_ms": 15200,
"recorded": false,
"forwarded_to_ingest": true,
"attempts": [
{ "provider": "vonage_identity_insights", "outcome": "timeout", "latency_ms": 15000 },
{ "provider": "sinch_number_lookup", "outcome": "ok", "latency_ms": 180 }
]
}forwarded_to_ingest means the existing asynchronous forward was dispatched, not that ingest completed or a playbook ran. A false value includes forward_skipped_reason. Lookup success is separate from downstream action success.
Lookup health and circuit states
The health action returns your preference, failover_available, failover_active and subject-free provider metrics. It requires the metrics scope or an organization administrator session. set_preference requires admin. Both work while failover dispatch is off, subject to tenant lifecycle and the existing quota checks. Neither request calls a carrier or reads a private provider key.
Success rate is ok_count divided by ok_count plus error_count over the complete five-minute database window. timeout_count is a subset of errors. p50_ms and p95_ms are discrete percentiles over all lookup samples in that window, including errors; circuit skips and account probes are excluded. The platform admin widget reads hosted accounts across their callers, while the tenant view includes its own accounts and entitled hosted accounts. Counts are aggregated in the database and are not capped at 1,000 rows.
An idle window has zero counts, null percentiles and fresh: false. The UI shows no recent lookups rather than healthy. A failed read renders an error or unavailable metrics. Account-probe freshness is separate: a successful number-free probe proves account/auth-service reachability, not SIM swap coverage, operator approval or a successful lookup.
Five consecutive retryable lookup failures open the account circuit. Success or a permanent error interrupts the closed streak. After 60 seconds, one leased half-open lookup may try the account; a matching unexpired result closes or reopens it. Another concurrent caller cannot take that lease, and an old success cannot close a newer circuit. Account probes never reset the lookup circuit.
Twilio FetchAccount, hosted Vonage balance and Sinch token probes are implemented behind a disabled active-probe gate and inactive cron. Tenant-owned Vonage Identity Insights active probing remains explicitly unsupported: no documented number-free endpoint compatible with the stored application credential has been verified. Passive lookup metrics and circuit tracking still work. No dummy phone request is used as a health probe.
Preference and health requests
POST the following JSON to https://api.passkeybridge.io/v1/shield-carrier-lookup with your existing authorization. These fields change only the saved preference; they cannot enable global or tenant rollout. Lists must be nonempty, unique and contain supported values.
{
"action": "set_preference",
"tenant_id": "f3600000-0000-4000-8000-000000000010",
"provider_order": ["vonage_identity_insights", "sinch_number_lookup"],
"failover_enabled": false,
"required_capabilities": ["sim_swap"]
}Read the saved preference and current metrics with action: health and tenant_id. Read the capability catalog with action: providers and tenant_id. There is no client access to the health tables; server routines enforce access. Health rows contain account association and closed outcome/timing fields, with no phone or subject digest. Passive-write outages can leave monitoring gaps, and seven-day retention removes old outcomes in bounded batches. See the OpenAPI document for the complete request/response schema.