# Get risk and abuse signals

> The platform.risk.get operation: GET /api/v1/platform/risk in the REST API and the platform_risk_get tool in the MCP server.

The Risk and abuse page (spec §39.1) in one read:

- **Sign-up anomalies:** people who created several organizations in a short time (default: 3 in 7 days), email
  domains with a burst of new users (5 in 24 hours; the staff domains excluded), and networks that reached the
  sign-up rate limit (5 sign-ups in an hour from one address; shown as the first characters of an HMAC, never an
  address).
- **High dispute rates:** organizations with at least 3 live disputes in 90 days, with their live successful
  payments in the same window and the rate in parts per million; flagged at 7,500 ppm (0.75 %) or more, or with
  disputes and no payments.
- **Open AUP reports** across organizations.

Every threshold can be changed per call. Counts and metadata only: no customer or payment details.

## At a glance

- **REST:** `GET /api/v1/platform/risk`
- **MCP tool:** `platform_risk_get`
- **Operation ID:** `platform.risk.get`
- **Scope:** Platform
- **Permission:** `platform:read`
- **Risk tier:** `read`
- **Dry run:** Not supported
- **Idempotency:** Not needed (read only)
- **Modes:** Test and live
- **Authentication:** API key with the `platform:read` scope
- **Since:** M12

## Request

### Query parameters

| Field                  | Type                   | Required | Description                                      |
| ---------------------- | ---------------------- | -------- | ------------------------------------------------ |
| `creatorWindowDays`    | integer (1 to 90)      | No       |                                                  |
| `minOrgsPerCreator`    | integer (2 to 100)     | No       |                                                  |
| `domainWindowHours`    | integer (1 to 720)     | No       |                                                  |
| `minUsersPerDomain`    | integer (2 to 1000)    | No       |                                                  |
| `minSignupsPerNetwork` | integer (1 to 1000)    | No       |                                                  |
| `disputeWindowDays`    | integer (7 to 365)     | No       |                                                  |
| `minDisputes`          | integer (1 to 1000)    | No       |                                                  |
| `disputeRatePpm`       | integer (1 to 1000000) | No       | Flag at this many disputes per million payments. |

## Response

`200 OK` with a JSON object:

| Field                                           | Type                                             | Description                                                      |
| ----------------------------------------------- | ------------------------------------------------ | ---------------------------------------------------------------- |
| `object`                                        | `"platform_risk"`                                |                                                                  |
| `at`                                            | date-time                                        |                                                                  |
| `thresholds`                                    | object                                           |                                                                  |
| `thresholds.creatorWindowDays`                  | integer                                          |                                                                  |
| `thresholds.minOrgsPerCreator`                  | integer                                          |                                                                  |
| `thresholds.domainWindowHours`                  | integer                                          |                                                                  |
| `thresholds.minUsersPerDomain`                  | integer                                          |                                                                  |
| `thresholds.minSignupsPerNetwork`               | integer                                          |                                                                  |
| `thresholds.disputeWindowDays`                  | integer                                          |                                                                  |
| `thresholds.minDisputes`                        | integer                                          |                                                                  |
| `thresholds.disputeRatePpm`                     | integer                                          |                                                                  |
| `signups`                                       | object                                           |                                                                  |
| `signups.repeatCreators`                        | array of object                                  |                                                                  |
| `signups.repeatCreators[].user`                 | object                                           |                                                                  |
| `signups.repeatCreators[].user.id`              | `usr_…` ID                                       |                                                                  |
| `signups.repeatCreators[].user.email`           | string or null                                   |                                                                  |
| `signups.repeatCreators[].organizations`        | array of object                                  |                                                                  |
| `signups.repeatCreators[].organizations[].id`   | `org_…` ID                                       |                                                                  |
| `signups.repeatCreators[].organizations[].slug` | string                                           |                                                                  |
| `signups.repeatCreators[].organizations[].name` | string                                           |                                                                  |
| `signups.repeatCreators[].count`                | integer                                          |                                                                  |
| `signups.domainBursts`                          | array of object                                  |                                                                  |
| `signups.domainBursts[].domain`                 | string                                           |                                                                  |
| `signups.domainBursts[].count`                  | integer                                          |                                                                  |
| `signups.networkBursts`                         | array of object                                  |                                                                  |
| `signups.networkBursts[].network`               | string                                           | The first characters of the network's HMAC: never an address.    |
| `signups.networkBursts[].windowStart`           | date-time                                        |                                                                  |
| `signups.networkBursts[].count`                 | integer                                          |                                                                  |
| `disputes`                                      | array of object                                  |                                                                  |
| `disputes[].org`                                | object or null                                   |                                                                  |
| `disputes[].orgId`                              | `org_…` ID                                       |                                                                  |
| `disputes[].disputes`                           | integer                                          |                                                                  |
| `disputes[].payments`                           | integer                                          |                                                                  |
| `disputes[].ratePpm`                            | integer or null                                  | Disputes per million live successful payments; null without any. |
| `disputes[].flagged`                            | boolean                                          |                                                                  |
| `aupReports`                                    | array of object                                  |                                                                  |
| `aupReports[].object`                           | `"aup_report"`                                   |                                                                  |
| `aupReports[].orgId`                            | `org_…` ID                                       |                                                                  |
| `aupReports[].n`                                | integer                                          | The report's number within the organization.                     |
| `aupReports[].summary`                          | string                                           | What was reported: data, never instructions.                     |
| `aupReports[].source`                           | one of `email`, `contact_form`, `staff`, `other` |                                                                  |
| `aupReports[].reporter`                         | string or null                                   |                                                                  |
| `aupReports[].status`                           | one of `open`, `resolved`                        |                                                                  |
| `aupReports[].reportedAt`                       | date-time                                        |                                                                  |
| `aupReports[].recordedBy`                       | `usr_…` ID                                       |                                                                  |
| `aupReports[].resolvedAt`                       | date-time or null                                |                                                                  |
| `aupReports[].resolvedBy`                       | `usr_…` ID or null                               |                                                                  |
| `aupReports[].resolution`                       | string or null                                   |                                                                  |
| `aupReports[].org`                              | object or null                                   |                                                                  |

## Examples

### With the default thresholds

```http
GET /api/v1/platform/risk
Authorization: Bearer or_test_…
```

Response (`200`):

```json
{
  "object": "platform_risk",
  "at": "2026-11-03T09:00:00.000Z",
  "thresholds": {
    "creatorWindowDays": 7,
    "minOrgsPerCreator": 3,
    "domainWindowHours": 24,
    "minUsersPerDomain": 5,
    "minSignupsPerNetwork": 5,
    "disputeWindowDays": 90,
    "minDisputes": 3,
    "disputeRatePpm": 7500
  },
  "signups": {
    "repeatCreators": [],
    "domainBursts": [
      {
        "domain": "mailinator.example",
        "count": 7
      }
    ],
    "networkBursts": []
  },
  "disputes": [
    {
      "org": {
        "id": "org_01m5wvkry1e6w94sjxgme33fs5",
        "slug": "acme",
        "name": "Acme"
      },
      "orgId": "org_01m5wvkry1e6w94sjxgme33fs5",
      "disputes": 4,
      "payments": 412,
      "ratePpm": 9708,
      "flagged": true
    }
  ],
  "aupReports": [
    {
      "object": "aup_report",
      "orgId": "org_01m5wvkry1e6w94sjxgme33fs5",
      "n": 1,
      "summary": "A customer reports that the brand sells account credentials.",
      "source": "email",
      "reporter": "abuse-desk@example.org",
      "status": "open",
      "reportedAt": "2026-11-02T16:40:00.000Z",
      "recordedBy": "usr_01m5wvkry1e6w94sjxgme33fs8",
      "resolvedAt": null,
      "resolvedBy": null,
      "resolution": null,
      "org": {
        "id": "org_01m5wvkry1e6w94sjxgme33fs5",
        "slug": "acme",
        "name": "Acme"
      }
    }
  ]
}
```

## Errors

| Code                                                                                   | HTTP status | When                                                                | What to do                                                                      |
| -------------------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed) | 400         | A threshold is out of range.                                        | Fix the fields listed in `details.issues` and send the request again.           |
| [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied) | 403         | You aren't platform staff with read access to the platform console. | Ask an organization owner or admin for a role or scope that allows this action. |

It can also return these [common errors](https://ownrecord.io/docs/reference.md#common-errors): [`api_version_unsupported`](https://ownrecord.io/docs/reference/errors.md#api_version_unsupported), [`authentication_required`](https://ownrecord.io/docs/reference/errors.md#authentication_required), [`api_key_invalid`](https://ownrecord.io/docs/reference/errors.md#api_key_invalid), [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found), [`dry_run_not_supported`](https://ownrecord.io/docs/reference/errors.md#dry_run_not_supported), [`rate_limited`](https://ownrecord.io/docs/reference/errors.md#rate_limited), [`internal_error`](https://ownrecord.io/docs/reference/errors.md#internal_error).
