> This page is for version v2 (default).
> For other versions, use one of these documentation indexes:
> - v2 (default): https://docs.pinnacle.sh/v-2/llms.txt
> - v1: https://docs.pinnacle.sh/v1/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.pinnacle.sh/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.pinnacle.sh/_mcp/server.

# Network APIs

> Verify phone number risk, subscriber details, and device possession with carrier-backed signals.

Network APIs help you make higher-confidence trust decisions for phone numbers. Use them during onboarding, account verification, account protection, or fraud review.

> **Limited availability**
>
> Network APIs are currently available only to select customers. To request access, contact [founders@pinnacle.sh](mailto:founders@pinnacle.sh).

## Capabilities

#### [SIM Swap](/api-reference/network/check-sim-swap)

Check whether a phone number's SIM changed recently.

#### [Subscriber Match](/api-reference/network/check-subscriber-match)

Compare user-provided identity attributes against the carrier record.

#### [Silent Auth](/api-reference/network/start-silent-auth)

Verify device possession using the user's cellular data path.

## Input constraints

Input constraints keep requests valid for carrier-backed checks and make request history predictable. Validate these fields before calling the API to avoid rejected requests.

All phone numbers must use E.164 format, for example `+14155550123`.

| Field         | Description and constraint                                                                                                                                                                               |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `requestId`   | Pinnacle-generated Network API request ID used to retrieve a prior request. It starts with `nar_` followed by 16 letters or numbers.                                                                     |
| `periodHours` | SIM Swap lookback window, in hours. Use a shorter window for recent-risk checks or a longer window for broader account review. Must be an integer from `1` to `2400`; defaults to `240`.                 |
| `clientRef`   | Your optional correlation ID, such as a user ID, session ID, or case ID. It is returned in request history to help reconcile checks with your own systems. Must be `1` to `40` characters when provided. |
| `attributes`  | Subscriber Match fields to compare against the carrier record. Provide at least one non-empty attribute; more attributes can improve the usefulness of the match result.                                 |
| `birthdate`   | Subscriber date of birth for Subscriber Match. Format as `YYYY-MM-DD`, for example `1990-01-31`.                                                                                                         |
| `pageIndex`   | Zero-based page number for listing request history. Use `0` for the first page, `1` for the second page, and so on. Must be `0` or greater; defaults to `0`.                                             |
| `pageSize`    | Number of request records to return per page. Use smaller values for quick UI loads and larger values for back-office review. Must be from `1` to `100`; defaults to `20`.                               |

## SIM Swap

Call [`POST /network/sim-swap`](/api-reference/network/check-sim-swap) with an E.164 phone number and an optional `periodHours` window. The response tells you whether the SIM was swapped during that window.

```json
{
  "phoneNumber": "+14155550123",
  "periodHours": 240
}
```

## Subscriber Match

Call [`POST /network/subscriber-match`](/api-reference/network/check-subscriber-match) with an E.164 phone number and at least one subscriber attribute. The response returns match strength for each attribute that can be evaluated.

```json
{
  "phoneNumber": "+14155550123",
  "attributes": {
    "givenName": "Jane",
    "familyName": "Doe",
    "postalCode": "94105"
  }
}
```

## Silent Auth

Silent Auth verifies that the user controls the device attached to the phone number. Your server starts the session, then the user's device completes the carrier check.

> **SDKs coming soon**
>
> Native SDKs for iOS, Android, and React Native are coming soon to simplify embedding the JSON flow and code capture in mobile applications.

#### Start the session

Your server calls [`POST /network/silent-auth`](/api-reference/network/start-silent-auth) with the user's phone number. Omit `format` for the hosted HTML flow, or set `format: "json"` for the JSON flow. The response includes `expiresAt` for the initial device handoff.

#### Run the device check

Open `browserUrl` for hosted sessions, or fetch `jsonUrl` for JSON sessions. Do not call either URL server-side.

#### Finish or read the result

The HTML flow completes the request in the browser. The JSON flow returns a `code` from your app's fetch call; send that code to your server, then call [`POST /network/silent-auth/{requestId}/check`](/api-reference/network/check-silent-auth).

> **Open Silent Auth URLs immediately**
>
> Silent Auth URLs expire 60 seconds after creation because the carrier device check must start promptly. If `expiresAt` has passed, start a new Silent Auth session before asking the user to try again.

```json
{
  "phoneNumber": "+14155550123",
  "clientRef": "user_123"
}
```

### HTML flow

Use `browserUrl` when you want Pinnacle to handle the device-check page.

Open the URL on the user's phone in a browser, mobile WebView, or app redirect. Pinnacle serves a hosted page that runs the carrier challenge and completes the Silent Auth request.

```json
{
  "requestId": "nar_1234567890ABCDEF",
  "format": "hosted",
  "browserUrl": "https://verify.pinnacle.sh/silent-auth/nar_1234567890ABCDEF?sessionToken=...",
  "expiresAt": "2026-06-12T18:30:00Z"
}
```

### JSON flow

Use `jsonUrl` when you are building a native mobile flow and do not want to open a browser. Your app fetches the URL directly from the user's cellular device and controls the UI itself.

Start the session with `format: "json"` so the device check redirects back to a JSON response instead of the hosted verification page.

```json
{
  "phoneNumber": "+14155550123",
  "clientRef": "user_123",
  "format": "json"
}
```

The start response includes only the URL for the requested flow:

```json
{
  "requestId": "nar_1234567890ABCDEF",
  "format": "json",
  "jsonUrl": "https://api.pinnacle.sh/public/network/silent-auth/nar_1234567890ABCDEF?sessionToken=...&format=json",
  "expiresAt": "2026-06-12T18:30:00Z"
}
```

Fetch `jsonUrl` from the user's phone with redirects enabled. Pinnacle validates the session, redirects through the carrier challenge, and the final response is JSON containing a verification `code`. Send that `code` to your server, then call [`POST /network/silent-auth/{requestId}/check`](/api-reference/network/check-silent-auth).

```json
{
  "code": "abc123"
}
```

Do not proxy `jsonUrl` through your backend. Silent Auth depends on the request leaving from the user's cellular data path.

> **Run on the user's cellular device**
>
> `browserUrl` and `jsonUrl` must be opened or fetched from the user's device, not server-side. The device must be using its cellular network. Wi-Fi-only paths, VPNs, iCloud Private Relay, and similar proxying products can prevent Silent Auth from working.

## Request history

Every Network API call creates a request record scoped to your team. Use [`POST /network/requests/list`](/api-reference/network/list-network-requests) to page through recent requests, or [`GET /network/requests/{requestId}`](/api-reference/network/get-network-request) to retrieve one request.

Request summaries include lifecycle timestamps, the request status, your `clientRef`, and the result fields returned by the original check.

```json
{
  "pageIndex": 0,
  "pageSize": 20,
  "type": "silent-auth",
  "status": "completed",
  "clientRef": "user_123"
}
```