---
title: "Find exposed OAuth tokens and SaaS credentials"
method: POST
path: "/v1/metered/oauth-watchlist"
tags: ["Identity exposure"]
---

# Find exposed OAuth tokens and SaaS credentials

`POST /v1/metered/oauth-watchlist`

## Request

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

Combines breach history against a watchlist of OAuth-capable apps with a live search of the stealer-log corpus. Returns matched apps with direct revoke links, plus any stolen credentials, category-scored: cloud consoles and code repositories CRITICAL, identity providers and payment processors HIGH, productivity SaaS MEDIUM.

**Billing.** $0.30 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.

**Note.** The stealer-corpus half of this check is non-fatal: if that query fails, breach-history results are still returned rather than failing the whole call.

## Request body

- object
  - `email` string, email, required: Email address to check.

## 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 7 days; clean results live 12 hours, 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.
    - `email` string: The normalised address that was checked.
    - `matched_count` integer: OAuth-capable apps matched via breach history.
    - `matched_apps` object[]: Apps matched from breach history.
      - `app` string: App or service name.
      - `source` string: Always `breach_history` for this list.
      - `breach_date` string: Date of the breach, YYYY-MM-DD.
      - `data_classes` string[]: Data types exposed.
      - `revoke_url` string: Direct link to the app's revoke-access page.
    - `stolen_token_count` integer: Credential records found in the stealer corpus.
    - `stolen_tokens` object[]: Stolen credentials, sorted most severe first.
      - `domain` string: Service the stolen session belongs to.
      - `session_type` string: `cookie` for a session cookie, `credential` for a username/password or token pair.
      - `cookie_name` string: Cookie or credential name. Never the value.
      - `severity` 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW': Severity derived from the service category.
      - `service_category` string: Category of the affected service, e.g. cloud_console, identity_provider, productivity.
      - `channel_source` string: Criminal channel or archive the record was collected from.
      - `ingested_at` string: When RelayShield ingested the record.
    - `highest_severity` 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'NONE': Highest severity across both signals. `NONE` when nothing was found.
    - `recommendation` string: Remediation text derived from the most severe signal present.
    - `checked_at` string, date-time: ISO 8601 UTC timestamp of when this check ran.

## Other responses

- `400`: `email` is missing or contains no '@'.
- `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.
- `429`: Upstream breach database rate limit reached.
- `502`: Upstream breach database unavailable.

---

[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)
