---
title: "Detect a recent SIM swap or carrier port"
method: POST
path: "/v1/metered/sim-swap"
tags: ["Identity exposure"]
---

# Detect a recent SIM swap or carrier port

`POST /v1/metered/sim-swap`

## Request

- Base URL: `https://api.relayshield.net`
- URL: `https://api.relayshield.net/v1/metered/sim-swap`
- Auth: one of:
  - API key in header `X-RS-API-KEY`
  - HTTP bearer

Queries live carrier data for the number. A recent swap is a strong signal of an account-takeover attempt against SMS-based 2FA, so call this before trusting an SMS OTP from a number you have not seen before.

**Billing.** $0.25 per successful call. Failed calls are never billed. Charged against prepaid credits when the balance covers it, otherwise metered to your card. Threat Intelligence subscribers and AWS Marketplace bundle customers call this at no extra charge.

## Request body

- object
  - `phone` string, required: Phone number in E.164 format. Must start with '+'. Rejected without it, because national formats are ambiguous across carriers.

## Response `200`

Success. `ok` is true and `data` holds the result.

- object
  - `ok` true, required
  - `data` object, required
    - `observed_at` string, date-time: When this verdict was observed. Cache keyed on this, not on receipt time.
    - `valid_for_seconds` integer: How long this verdict can be cached before it should be re-checked. Flagged results live 24 hours; clean results live 15 minutes, because a hit stays a hit while a clean answer is the one that flips without telling whoever cached it. A degraded result lives 5 minutes. This is a caching hint and a policy default, not a measurement and not a safety guarantee: how fast a verdict really goes stale is bounded by upstream detection latency, which we do not control.
    - `expires_at` string, date-time: observed_at plus valid_for_seconds, precomputed.
    - `degraded` boolean: True when this answer was assembled from incomplete or failed upstream data. Treat it as NO VERDICT, never as clean. An outage that returns an empty finding list is otherwise indistinguishable from a real all-clear, and it fails in the permissive direction.
    - `phone` string: The number that was checked, echoed as supplied.
    - `swapped` boolean: True when the carrier reports a SIM swap or port in the lookback period. False means the carrier affirmatively reported no swap. When carrier data is unavailable the endpoint returns 503 rather than False, so a 200 response is always a real verdict.
    - `swap_timestamp` string: When the swap occurred. Empty string when no swap is reported.
    - `carrier` string: Current carrier name. Empty when the carrier does not disclose it.
    - `checked_at` string, date-time: ISO 8601 UTC timestamp of when this check ran.

## Other responses

- `400`: `phone` is missing or not in E.164 format (must start with '+').
- `401`: Missing or invalid API key.
- `402`: No credits and no active subscription. The response carries `topup_url`.
- `405`: Wrong HTTP method. Every endpoint is POST.
- `502`: Carrier lookup provider unavailable or returned an unexpected status.
- `503`: The carrier returned no SIM swap data for this number, so no verdict was produced. This call is not billed. Retry later rather than treating it as a clean result.

---

[API](https://skmtc.dev/relayshield/apis/relayshield-api.md) · [All operations](https://skmtc.dev/relayshield/apis/relayshield-api/llms.txt) · [OpenAPI document](https://skmtc.dev/relayshield/apis/relayshield-api/revisions/4d4721b936dd?raw)
