# AIRiskDB API Reference



## Base URLs

| Resource      | URL                           |
| ------------- | ----------------------------- |
| API root      | `https://api.airiskdb.com`    |
| Versioned API | `https://api.airiskdb.com/v1` |

***

## Public API Routes

### Signals

| Method | Path                      | Required Scope  | Description                                              | Response Codes                    |
| ------ | ------------------------- | --------------- | -------------------------------------------------------- | --------------------------------- |
| `POST` | `/v1/signals`             | `signals:write` | Create one signal and trigger enrichment when applicable | `202`, `400`, `401`, `500`        |
| `POST` | `/v1/signals/bulk`        | `signals:write` | Create 1 to 500 signals in one request                   | `202`, `400`, `401`, `500`        |
| `GET`  | `/v1/signals/{signal_id}` | `signals:read`  | Retrieve a stored signal                                 | `200`, `400`, `401`, `404`, `500` |

### Assets

| Method | Path                                | Required Scope | Description                                     | Response Codes                    |
| ------ | ----------------------------------- | -------------- | ----------------------------------------------- | --------------------------------- |
| `GET`  | `/v1/assets`                        | `assets:read`  | List assets with filters and pagination         | `200`, `400`, `401`, `500`        |
| `GET`  | `/v1/assets/lookup`                 | `assets:read`  | Lookup assets by fingerprint or name-based keys | `200`, `400`, `401`, `500`        |
| `GET`  | `/v1/assets/{fingerprint}`          | `assets:read`  | Retrieve one asset by fingerprint               | `200`, `400`, `401`, `404`, `500` |
| `GET`  | `/v1/assets/{fingerprint}/findings` | `assets:read`  | Retrieve findings for an enriched asset         | `200`, `400`, `401`, `404`, `500` |
| `GET`  | `/v1/assets/{fingerprint}/aibom`    | `assets:read`  | Retrieve AI-BOM data for an enriched asset      | `200`, `400`, `401`, `404`, `500` |
| `GET`  | `/v1/assets/{fingerprint}/threats`  | `assets:read`  | List threats that match an asset                | `200`, `400`, `401`, `404`, `500` |

### Threats

| Method | Path                      | Required Scope  | Description                       | Response Codes                           |
| ------ | ------------------------- | --------------- | --------------------------------- | ---------------------------------------- |
| `POST` | `/v1/threats`             | `threats:write` | Create a shared threat record     | `201`, `400`, `401`, `403`, `500`        |
| `GET`  | `/v1/threats`             | `threats:read`  | List shared threat records        | `200`, `400`, `401`, `500`               |
| `GET`  | `/v1/threats/{threat_id}` | `threats:read`  | Retrieve one threat by ID         | `200`, `400`, `401`, `404`, `500`        |
| `POST` | `/v1/threats/{threat_id}` | `threats:write` | Update mutable fields on a threat | `200`, `400`, `401`, `403`, `404`, `500` |

### Webhooks

| Method | Path           | Required Scope   | Description                   | Response Codes             |
| ------ | -------------- | ---------------- | ----------------------------- | -------------------------- |
| `POST` | `/v1/webhooks` | `webhooks:write` | Create a webhook subscription | `201`, `400`, `401`, `500` |

***

## Authentication and Scopes

Every `/v1/*` route requires:

```http
Authorization: Bearer <AIRISKDB_API_KEY>
```

Public API keys can be issued with these scopes:

| Scope            | Allows                                                                  |
| ---------------- | ----------------------------------------------------------------------- |
| `signals:write`  | Submit one or more observed asset signals                               |
| `signals:read`   | Read submitted signals                                                  |
| `assets:read`    | List, lookup, and retrieve assets, findings, AI-BOMs, and asset threats |
| `threats:read`   | List and retrieve shared threat records                                 |
| `threats:write`  | Create and update shared threat records                                 |
| `webhooks:write` | Register webhook subscriptions                                          |

Invalid, expired, revoked, or missing keys return `401 authentication_error`. Keys without the required scope return `403 permission_error`.

***

## Idempotency

All `POST` routes require:

```http
Idempotency-Key: <uuid>
```

Idempotency keys are scoped by method, path, livemode, and request body.

| Behavior                                    | Result                            |
| ------------------------------------------- | --------------------------------- |
| First successful request with a new key     | Response is processed and cached  |
| Same key, same method, same path, same body | Cached response is replayed       |
| Same key with a different request body      | `400 idempotency_replay_mismatch` |
| Missing or invalid key on `POST`            | `400 invalid_request_error`       |

Keys are retained for a 24-hour window.

***

## Pagination

List routes use cursor-style pagination.

| Parameter        | Description                                                      |
| ---------------- | ---------------------------------------------------------------- |
| `limit`          | Optional page size. Defaults to `20`. Minimum `1`, maximum `100` |
| `starting_after` | Optional forward cursor                                          |
| `ending_before`  | Optional reverse cursor on routes that support it                |

List responses use this envelope:

```json
{
  "object": "list",
  "data": [],
  "has_more": false,
  "url": "/v1/assets",
  "next_cursor": "aset_123"
}
```

Use `next_cursor` as the next `starting_after` value while `has_more` is `true`.

***

## Expansions

AIRiskDB uses repeated `expand[]` query parameters.

| Expansion           | Supported Routes                                                          |
| ------------------- | ------------------------------------------------------------------------- |
| `expand[]=findings` | `GET /v1/assets`, `GET /v1/assets/{fingerprint}`, `GET /v1/assets/lookup` |
| `expand[]=aibom`    | `GET /v1/assets`, `GET /v1/assets/{fingerprint}`, `GET /v1/assets/lookup` |
| `expand[]=threats`  | `GET /v1/assets/{fingerprint}/findings`                                   |

Example:

```bash
curl -s "https://api.airiskdb.com/v1/assets/<FINGERPRINT>?expand[]=findings&expand[]=aibom" \
  -H "Authorization: Bearer <AIRISKDB_API_KEY>"
```

When an expandable field is not expanded, it may be absent, `null`, or represented as a stored identifier depending on the resource.

***

## Query Parameters

### `GET /v1/assets`

| Parameter                 | Description                                                       |
| ------------------------- | ----------------------------------------------------------------- |
| `limit`                   | Page size                                                         |
| `starting_after`          | Forward pagination cursor                                         |
| `ending_before`           | Reverse pagination cursor                                         |
| `asset_type`              | Filter by asset type                                              |
| `enrichment_status`       | Filter by `pending`, `enriched`, `failed`, or `stale`             |
| `intrinsic_risk_severity` | Filter by `critical`, `high`, `medium`, `low`, or `informational` |
| `expand[]`                | `findings` or `aibom`                                             |

### `GET /v1/assets/lookup`

| Parameter            | Description                                                         |
| -------------------- | ------------------------------------------------------------------- |
| `fingerprints`       | Repeatable exact fingerprint lookup                                 |
| `lookup_name`        | Repeatable asset name lookup                                        |
| `lookup_version`     | Repeatable version value aligned by index with `lookup_name`        |
| `lookup_ecosystem`   | Repeatable ecosystem value aligned by index with `lookup_name`      |
| `lookup_fingerprint` | Repeatable fallback fingerprint aligned by index with `lookup_name` |
| `include_candidates` | Set to `true` to include candidate matches                          |
| `expand[]`           | `findings` or `aibom`                                               |

Lookup notes:

* Combined `fingerprints` and lookup keys must include between 1 and 500 entries.
* `lookup_name` is required when any other `lookup_*` parameter is used.
* Repeatable `lookup_*` parameters are aligned by index.
* Name-only lookup can return flexible matches and candidates.

### `GET /v1/assets/{fingerprint}/aibom`

| Parameter          | Description                               |
| ------------------ | ----------------------------------------- |
| `format=json`      | Default. Returns the full AI-BOM resource |
| `format=spdx_json` | Returns only the SPDX JSON document       |
| `format=spdx_tv`   | Returns SPDX tag-value text               |

### `GET /v1/threats`

| Parameter             | Description                   |
| --------------------- | ----------------------------- |
| `limit`               | Page size                     |
| `starting_after`      | Forward pagination cursor     |
| `ending_before`       | Reverse pagination cursor     |
| `category`            | Filter by threat category     |
| `severity`            | Filter by risk severity       |
| `affected_asset_type` | Filter by affected asset type |

***

## Error Responses

All error responses use the same envelope:

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "missing_required_param",
    "param": "fingerprint",
    "message": "The fingerprint field is required.",
    "request_id": "req_1234567890abcdef12345678"
  }
}
```

Known error types:

| Type                    | Meaning                                              |
| ----------------------- | ---------------------------------------------------- |
| `invalid_request_error` | The request is malformed or failed validation        |
| `authentication_error`  | The API key is missing, invalid, expired, or revoked |
| `permission_error`      | The API key does not have the required scope         |
| `not_found_error`       | The requested resource does not exist                |
| `conflict_error`        | The request conflicts with current resource state    |
| `api_error`             | AIRiskDB encountered an internal error               |

Every response includes an `X-Request-Id` header. Error responses also include the request ID inside `error.request_id`. Include this ID when contacting SuperAlign support.

***

## Resource Notes

### Signal

A signal is an immutable observation submitted by a caller. Required fields are:

| Field         | Description                        |
| ------------- | ---------------------------------- |
| `fingerprint` | Asset fingerprint                  |
| `asset_type`  | Supported asset type               |
| `org_id`      | Organization identifier            |
| `observed_at` | Unix timestamp for the observation |

Optional fields include `name`, `version`, `source_url`, `raw_manifest`, and `metadata`.

### Asset

Assets are global and fingerprint-keyed. Important fields include `enrichment_status`, `intrinsic_risk_score`, `intrinsic_risk_severity`, `publisher_trust`, `benchmark_summary`, `findings`, and `aibom`.

### Finding

A finding captures derived capabilities, related threat links, ATLAS techniques, CVE IDs, score breakdowns, and benchmark details.

### AI-BOM

An AI-BOM contains SPDX metadata, a machine-readable SPDX document, normalized component inventory, model lineage when derivable, and a monotonically increasing `bom_version`.

### Threat

A threat is a shared intelligence record. Threats can include category, title, severity, confidence, affected asset types, fingerprints, ATLAS techniques, CVE ID, remediation, source, risk penalty, and metadata.

### Webhook

A webhook subscription includes URL, event list, status, metadata, and a generated secret. The secret is returned once in the creation response.
