> ## Documentation Index
> Fetch the complete documentation index at: https://docs.corsa.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage Alerts & Cases - Bulk Operations & Status Updates

> Batch create, bulk update, assign, and escalate compliance alerts and investigation cases via the Corsa API.

This guide covers advanced operations for managing **Alerts** and **Cases** - including batch creation, bulk assignments, status updates, escalation, and entity associations.

Full API endpoint details are available in the [API Reference](https://api.corsa.finance/api-spec.json) (requires API credentials).

<Note>For basic alert and case creation, see the [Ingesting Alerts & Cases](/api/ingesting-alerts-and-cases) guide first.</Note>

***

## Alerts

### Get an Alert

**Endpoint:** `GET /v1/alerts/{alertId}`

Retrieve a single alert by its Corsa ID.

<CodeGroup>
  ```json REST API theme={null}
  GET /v1/alerts/alert-uuid-123
  ```

  ```typescript Javascript theme={null}
  const alert = await corsa.alerts.getAlert("alert-uuid-123");
  ```

  ```python Python theme={null}
  from corsa_sdk.api.alerts.get_alert import _get_kwargs

  resp = http.request(**_get_kwargs(alert_id="alert-uuid-123"))
  alert = resp.json()
  ```
</CodeGroup>

***

### Step 1: Batch Create Alerts

**Endpoint:** `POST /v1/alerts/batch`

Create up to 50 alerts in a single request. Each alert in the array follows the same schema as the single-create endpoint.

<CodeGroup>
  ```json REST API theme={null}
  POST /v1/alerts/batch
  Content-Type: application/json

  {
    "alerts": [
      {
        "referenceId": "EXT-ALERT-001",
        "category": "TRANSACTION_MONITORING",
        "priority": "HIGH",
        "status": "NEW",
        "description": "Large withdrawal detected for a high-risk account."
      },
      {
        "referenceId": "EXT-ALERT-002",
        "category": "SCREENING_SANCTIONS",
        "priority": "MEDIUM",
        "status": "NEW",
        "description": "Potential sanctions match found during screening."
      }
    ],
    "upsert": true
  }
  ```

  ```typescript Javascript theme={null}
  const result = await corsa.alerts.createAlertsBatch({
    alerts: [
      {
        referenceId: "EXT-ALERT-001",
        category: "TRANSACTION_MONITORING",
        priority: "HIGH",
        status: "NEW",
        description: "Large withdrawal detected for a high-risk account.",
      },
      {
        referenceId: "EXT-ALERT-002",
        category: "SCREENING_SANCTIONS",
        priority: "MEDIUM",
        status: "NEW",
        description: "Potential sanctions match found during screening.",
      },
    ],
    upsert: true,
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.alerts.create_alerts_batch import _get_kwargs
  from corsa_sdk.models.batch_create_alerts_dto import BatchCreateAlertsDto

  resp = http.request(**_get_kwargs(
      body=BatchCreateAlertsDto(
          alerts=[
              {"referenceId": "EXT-ALERT-001", "category": "TRANSACTION_MONITORING", "priority": "HIGH", "status": "NEW", "description": "Large withdrawal detected for a high-risk account."},
              {"referenceId": "EXT-ALERT-002", "category": "SCREENING_SANCTIONS", "priority": "MEDIUM", "status": "NEW", "description": "Potential sanctions match found during screening."},
          ],
          upsert=True,
      ),
  ))
  result = resp.json()
  ```
</CodeGroup>

<Note>Maximum 50 alerts per batch request. Set `upsert: true` to update existing alerts matched by `referenceId`.</Note>

***

### Step 2: Bulk Update Alerts

**Endpoint:** `PATCH /v1/alerts/bulk/update`

Apply the same field changes to up to 100 alerts in one request. Use this when you need to set the same priority, category, or custom fields across a group of alerts.

<CodeGroup>
  ```json REST API theme={null}
  PATCH /v1/alerts/bulk/update
  Content-Type: application/json

  {
    "alertIds": ["alert-uuid-1", "alert-uuid-2", "alert-uuid-3"],
    "update": {
      "priority": "HIGH",
      "customFields": {
        "reviewTier": {
          "label": "Review Tier",
          "value": "2"
        }
      }
    }
  }
  ```

  ```typescript Javascript theme={null}
  const result = await corsa.alerts.bulkUpdateAlert({
    alertIds: ["alert-uuid-1", "alert-uuid-2", "alert-uuid-3"],
    update: {
      priority: "HIGH",
      customFields: {
        reviewTier: {
          label: "Review Tier",
          value: "2",
        },
      },
    },
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.alerts.bulk_update_alert import _get_kwargs
  from corsa_sdk.models.bulk_update_alert_dto import BulkUpdateAlertDto

  resp = http.request(**_get_kwargs(
      body=BulkUpdateAlertDto(
          alert_ids=["alert-uuid-1", "alert-uuid-2", "alert-uuid-3"],
          update={"priority": "HIGH", "customFields": {"reviewTier": {"label": "Review Tier", "value": "2"}}},
      ),
  ))
  result = resp.json()
  ```
</CodeGroup>

<Note>Maximum 100 alerts per request. Only the fields in `update` are modified; all other fields remain unchanged.</Note>

***

### Step 3: Update an Alert

**Endpoint:** `PUT /v1/alerts/{alertId}/update`

Update any field on an existing alert - priority, status, assignee, associated entities, and more.

<CodeGroup>
  ```json REST API theme={null}
  PUT /v1/alerts/alert-uuid/update
  Content-Type: application/json

  {
    "priority": "HIGH",
    "status": "IN_REVIEW",
    "assigneeId": "analyst-uuid",
    "category": "TRANSACTION_MONITORING",
    "description": "Updated: confirmed suspicious pattern in withdrawal activity.",
    "associatedClients": ["client-uuid-1"],
    "associatedTransactions": ["transaction-uuid-1"],
    "dueDate": "2024-02-01T17:00:00Z",
    "customFields": {
      "internalScore": {
        "label": "Internal Score",
        "value": "95"
      }
    }
  }
  ```

  ```typescript Javascript theme={null}
  const updated = await corsa.alerts.updateAlert("alert-uuid", {
    priority: "HIGH",
    status: "IN_REVIEW",
    assigneeId: "analyst-uuid",
    category: "TRANSACTION_MONITORING",
    description: "Updated: confirmed suspicious pattern in withdrawal activity.",
    associatedClients: ["client-uuid-1"],
    associatedTransactions: ["transaction-uuid-1"],
    dueDate: "2024-02-01T17:00:00Z",
    customFields: {
      internalScore: {
        label: "Internal Score",
        value: "95",
      },
    },
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.alerts.update_alert import _get_kwargs
  from corsa_sdk.models.update_alert_dto import UpdateAlertDto

  resp = http.request(**_get_kwargs(
      alert_id="alert-uuid",
      body=UpdateAlertDto(
          priority="HIGH",
          status="IN_REVIEW",
          assignee_id="analyst-uuid",
          description="Updated: confirmed suspicious pattern in withdrawal activity.",
      ),
  ))
  updated = resp.json()
  ```
</CodeGroup>

### Alert Statuses

| Status      | Description                         |
| ----------- | ----------------------------------- |
| `NEW`       | Newly created, not yet reviewed     |
| `IN_REVIEW` | Under active review by an analyst   |
| `ESCALATED` | Escalated to a case                 |
| `RESOLVED`  | Resolved (no further action needed) |

### Alert Categories

| Category                         | Description                     |
| -------------------------------- | ------------------------------- |
| `KYC`                            | Know Your Customer              |
| `KYB`                            | Know Your Business              |
| `TRANSACTION_MONITORING`         | Fiat transaction monitoring     |
| `ONCHAIN_TRANSACTION_MONITORING` | On-chain transaction monitoring |
| `SCREENING_SANCTIONS`            | Sanctions screening             |
| `SCREENING_PEP`                  | PEP screening                   |
| `SCREENING_ADVERSE_MEDIA`        | Adverse media screening         |
| `SCREENING_REGULATORY`           | Regulatory screening            |
| `SCREENING_OTHER`                | Other screening type            |
| `FRAUD`                          | Fraud detection                 |
| `PERIODIC_REVIEW`                | Periodic review                 |
| `EDD`                            | Enhanced Due Diligence          |
| `OTHER`                          | Other                           |

***

### Step 4: Bulk Assign Alerts

**Endpoint:** `PATCH /v1/alerts/bulk/assign`

Assign or unassign up to 100 alerts at once.

<CodeGroup>
  ```json REST API theme={null}
  PATCH /v1/alerts/bulk/assign
  Content-Type: application/json

  {
    "alertIds": ["alert-uuid-1", "alert-uuid-2", "alert-uuid-3"],
    "assigneeId": "analyst-uuid"
  }
  ```

  ```typescript Javascript theme={null}
  const result = await corsa.alerts.bulkAssignAlert({
    alertIds: ["alert-uuid-1", "alert-uuid-2", "alert-uuid-3"],
    assigneeId: "analyst-uuid",
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.alerts.bulk_assign_alert import _get_kwargs
  from corsa_sdk.models.bulk_assign_alert_dto import BulkAssignAlertDto

  resp = http.request(**_get_kwargs(
      body=BulkAssignAlertDto(
          alert_ids=["alert-uuid-1", "alert-uuid-2", "alert-uuid-3"],
          assignee_id="analyst-uuid",
      ),
  ))
  result = resp.json()
  ```
</CodeGroup>

<Note>Omit `assigneeId` or set it to `null` to unassign alerts.</Note>

***

### Step 5: Bulk Update Alert Status

**Endpoint:** `PATCH /v1/alerts/bulk/status`

Update the status of up to 100 alerts at once, with an optional decision reason.

<CodeGroup>
  ```json REST API theme={null}
  PATCH /v1/alerts/bulk/status
  Content-Type: application/json

  {
    "alertIds": ["alert-uuid-1", "alert-uuid-2"],
    "status": "RESOLVED",
    "decision": {
      "reason": "False positive - confirmed legitimate activity after review."
    }
  }
  ```

  ```typescript Javascript theme={null}
  const result = await corsa.alerts.bulkUpdateAlertStatus({
    alertIds: ["alert-uuid-1", "alert-uuid-2"],
    status: "RESOLVED",
    decision: {
      reason: "False positive - confirmed legitimate activity after review.",
    },
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.alerts.bulk_update_alert_status import _get_kwargs
  from corsa_sdk.models.bulk_update_alert_status_dto import BulkUpdateAlertStatusDto

  resp = http.request(**_get_kwargs(
      body=BulkUpdateAlertStatusDto(
          alert_ids=["alert-uuid-1", "alert-uuid-2"],
          status="RESOLVED",
          decision={"reason": "False positive - confirmed legitimate activity after review."},
      ),
  ))
  result = resp.json()
  ```
</CodeGroup>

***

### Step 6: Bulk Escalate Alerts to Cases

**Endpoint:** `PATCH /v1/alerts/bulk/escalate`

Escalate multiple alerts to cases in a single request. Each alert gets its own case.

<CodeGroup>
  ```json REST API theme={null}
  PATCH /v1/alerts/bulk/escalate
  Content-Type: application/json

  {
    "alertIds": ["alert-uuid-1", "alert-uuid-2"],
    "reason": "Pattern of suspicious transactions requires formal investigation.",
    "description": "Multiple high-value transactions flagged across related accounts.",
    "caseCategory": "TRANSACTION_MONITORING",
    "casePriority": "HIGH",
    "caseAssigneeId": "analyst-uuid",
    "dueDate": "2024-02-15T17:00:00Z"
  }
  ```

  ```typescript Javascript theme={null}
  const result = await corsa.alerts.bulkEscalateAlert({
    alertIds: ["alert-uuid-1", "alert-uuid-2"],
    reason: "Pattern of suspicious transactions requires formal investigation.",
    description: "Multiple high-value transactions flagged across related accounts.",
    caseCategory: "TRANSACTION_MONITORING",
    casePriority: "HIGH",
    caseAssigneeId: "analyst-uuid",
    dueDate: "2024-02-15T17:00:00Z",
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.alerts.bulk_escalate_alert import _get_kwargs
  from corsa_sdk.models.bulk_escalate_alert_dto import BulkEscalateAlertDto

  resp = http.request(**_get_kwargs(
      body=BulkEscalateAlertDto(
          alert_ids=["alert-uuid-1", "alert-uuid-2"],
          reason="Pattern of suspicious transactions requires formal investigation.",
          description="Multiple high-value transactions flagged across related accounts.",
          case_category="TRANSACTION_MONITORING",
          case_priority="HIGH",
          case_assignee_id="analyst-uuid",
          due_date="2024-02-15T17:00:00Z",
      ),
  ))
  result = resp.json()
  ```
</CodeGroup>

***

### Step 7: Associate Entities with Alerts

Link clients or transactions to an existing alert.

**Associate clients:** `PUT /v1/alerts/{alertId}/clients`

The request body is a plain JSON array of client IDs.

<CodeGroup>
  ```json REST API theme={null}
  PUT /v1/alerts/alert-uuid/clients
  Content-Type: application/json

  ["client-uuid-1", "client-uuid-2"]
  ```

  ```typescript Javascript theme={null}
  await corsa.alerts.associateAlertWithClients(
    "alert-uuid",
    ["client-uuid-1", "client-uuid-2"]
  );
  ```

  ```python Python theme={null}
  from corsa_sdk.api.alerts.associate_alert_with_clients import _get_kwargs

  resp = http.request(**_get_kwargs(
      alert_id="alert-uuid",
      body=["client-uuid-1", "client-uuid-2"],
  ))
  ```
</CodeGroup>

**Associate transactions:** `PUT /v1/alerts/{alertId}/transactions`

<CodeGroup>
  ```json REST API theme={null}
  PUT /v1/alerts/alert-uuid/transactions
  Content-Type: application/json

  ["transaction-uuid-1"]
  ```

  ```typescript Javascript theme={null}
  await corsa.alerts.associateAlertWithTransactions(
    "alert-uuid",
    ["transaction-uuid-1"]
  );
  ```

  ```python Python theme={null}
  from corsa_sdk.api.alerts.associate_alert_with_transactions import _get_kwargs

  resp = http.request(**_get_kwargs(
      alert_id="alert-uuid",
      body=["transaction-uuid-1"],
  ))
  ```
</CodeGroup>

***

## Cases

### Get a Case

**Endpoint:** `GET /v1/cases/{caseId}`

Retrieve a single case by its Corsa ID.

<CodeGroup>
  ```json REST API theme={null}
  GET /v1/cases/case-uuid-123
  ```

  ```typescript Javascript theme={null}
  const case_ = await corsa.cases.getCase("case-uuid-123");
  ```

  ```python Python theme={null}
  from corsa_sdk.api.cases.get_case import _get_kwargs

  resp = http.request(**_get_kwargs(case_id="case-uuid-123"))
  case_ = resp.json()
  ```
</CodeGroup>

***

### Step 8: Batch Create Cases

**Endpoint:** `POST /v1/cases/batch`

Create up to 50 cases in a single request. Each case in the array follows the same schema as the single-create endpoint.

<CodeGroup>
  ```json REST API theme={null}
  POST /v1/cases/batch
  Content-Type: application/json

  {
    "cases": [
      {
        "referenceId": "CASE-EXT-001",
        "category": "TRANSACTION_MONITORING",
        "priority": "HIGH",
        "description": "Suspicious withdrawal pattern identified across multiple accounts."
      },
      {
        "referenceId": "CASE-EXT-002",
        "category": "KYC",
        "priority": "MEDIUM",
        "description": "KYC documents expired — enhanced review required."
      }
    ]
  }
  ```

  ```typescript Javascript theme={null}
  const result = await corsa.cases.createCasesBatch({
    cases: [
      {
        referenceId: "CASE-EXT-001",
        category: "TRANSACTION_MONITORING",
        priority: "HIGH",
        description: "Suspicious withdrawal pattern identified across multiple accounts.",
      },
      {
        referenceId: "CASE-EXT-002",
        category: "KYC",
        priority: "MEDIUM",
        description: "KYC documents expired — enhanced review required.",
      },
    ],
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.cases.create_cases_batch import _get_kwargs
  from corsa_sdk.models.batch_create_cases_dto import BatchCreateCasesDto

  resp = http.request(**_get_kwargs(
      body=BatchCreateCasesDto(
          cases=[
              {"referenceId": "CASE-EXT-001", "category": "TRANSACTION_MONITORING", "priority": "HIGH", "description": "Suspicious withdrawal pattern identified across multiple accounts."},
              {"referenceId": "CASE-EXT-002", "category": "KYC", "priority": "MEDIUM", "description": "KYC documents expired — enhanced review required."},
          ],
      ),
  ))
  result = resp.json()
  ```
</CodeGroup>

<Note>Maximum 50 cases per batch request.</Note>

***

### Step 9: Update a Case

**Endpoint:** `PUT /v1/cases/{caseId}/update`

Update case details, reassign, change priority, or link additional entities.

<CodeGroup>
  ```json REST API theme={null}
  PUT /v1/cases/case-uuid/update
  Content-Type: application/json

  {
    "priority": "HIGH",
    "assigneeId": "senior-analyst-uuid",
    "reviewersIds": ["reviewer-uuid-1", "reviewer-uuid-2"],
    "description": "Updated investigation scope to include related accounts.",
    "status": {
      "status": "UNDER_INVESTIGATION",
      "reason": "Additional evidence found"
    },
    "alertsIds": ["alert-uuid-1", "alert-uuid-2"],
    "transactionsIds": ["transaction-uuid-1"],
    "clientsIds": ["client-uuid-1"],
    "dueDate": "2024-03-01T17:00:00Z"
  }
  ```

  ```typescript Javascript theme={null}
  const updated = await corsa.cases.updateCase("case-uuid", {
    priority: "HIGH",
    assigneeId: "senior-analyst-uuid",
    reviewersIds: ["reviewer-uuid-1", "reviewer-uuid-2"],
    description: "Updated investigation scope to include related accounts.",
    status: {
      status: "UNDER_INVESTIGATION",
      reason: "Additional evidence found",
    },
    alertsIds: ["alert-uuid-1", "alert-uuid-2"],
    transactionsIds: ["transaction-uuid-1"],
    clientsIds: ["client-uuid-1"],
    dueDate: "2024-03-01T17:00:00Z",
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.cases.update_case import _get_kwargs
  from corsa_sdk.models.update_case_dto import UpdateCaseDto

  resp = http.request(**_get_kwargs(
      case_id="case-uuid",
      body=UpdateCaseDto(
          priority="HIGH",
          assignee_id="senior-analyst-uuid",
          reviewers_ids=["reviewer-uuid-1", "reviewer-uuid-2"],
          description="Updated investigation scope to include related accounts.",
      ),
  ))
  updated = resp.json()
  ```
</CodeGroup>

### Case Statuses

| Status                     | Description                      |
| -------------------------- | -------------------------------- |
| `NEW`                      | Newly created                    |
| `UNDER_INVESTIGATION`      | Active investigation in progress |
| `PENDING_EDD`              | Awaiting Enhanced Due Diligence  |
| `PENDING_RFI`              | Awaiting Request for Information |
| `PENDING_REVIEW`           | Awaiting supervisory review      |
| `CLOSED_DISMISSED`         | Closed - no further action       |
| `CLOSED_ESCALATION_TO_SAR` | Closed - escalated to SAR filing |

***

### Step 10: Bulk Update Cases

**Endpoint:** `PATCH /v1/cases/bulk/update`

Apply the same field changes to up to 100 cases in one request.

<CodeGroup>
  ```json REST API theme={null}
  PATCH /v1/cases/bulk/update
  Content-Type: application/json

  {
    "caseIds": ["case-uuid-1", "case-uuid-2", "case-uuid-3"],
    "update": {
      "priority": "HIGH",
      "customFields": {
        "investigationTier": {
          "label": "Investigation Tier",
          "value": "2"
        }
      }
    }
  }
  ```

  ```typescript Javascript theme={null}
  const result = await corsa.cases.bulkUpdateCase({
    caseIds: ["case-uuid-1", "case-uuid-2", "case-uuid-3"],
    update: {
      priority: "HIGH",
      customFields: {
        investigationTier: {
          label: "Investigation Tier",
          value: "2",
        },
      },
    },
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.cases.bulk_update_case import _get_kwargs
  from corsa_sdk.models.bulk_update_case_dto import BulkUpdateCaseDto

  resp = http.request(**_get_kwargs(
      body=BulkUpdateCaseDto(
          case_ids=["case-uuid-1", "case-uuid-2", "case-uuid-3"],
          update={"priority": "HIGH", "customFields": {"investigationTier": {"label": "Investigation Tier", "value": "2"}}},
      ),
  ))
  result = resp.json()
  ```
</CodeGroup>

<Note>Maximum 100 cases per request. Only the fields in `update` are modified; all other fields remain unchanged.</Note>

***

### Step 11: Bulk Assign Cases

**Endpoint:** `PATCH /v1/cases/bulk/assign`

Assign or unassign up to 100 cases at once.

<CodeGroup>
  ```json REST API theme={null}
  PATCH /v1/cases/bulk/assign
  Content-Type: application/json

  {
    "caseIds": ["case-uuid-1", "case-uuid-2"],
    "assigneeId": "analyst-uuid"
  }
  ```

  ```typescript Javascript theme={null}
  const result = await corsa.cases.bulkAssignCase({
    caseIds: ["case-uuid-1", "case-uuid-2"],
    assigneeId: "analyst-uuid",
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.cases.bulk_assign_case import _get_kwargs
  from corsa_sdk.models.bulk_assign_case_dto import BulkAssignCaseDto

  resp = http.request(**_get_kwargs(
      body=BulkAssignCaseDto(
          case_ids=["case-uuid-1", "case-uuid-2"],
          assignee_id="analyst-uuid",
      ),
  ))
  result = resp.json()
  ```
</CodeGroup>

***

### Step 12: Bulk Update Case Status

**Endpoint:** `PATCH /v1/cases/bulk/status`

<CodeGroup>
  ```json REST API theme={null}
  PATCH /v1/cases/bulk/status
  Content-Type: application/json

  {
    "caseIds": ["case-uuid-1", "case-uuid-2"],
    "status": "CLOSED_DISMISSED",
    "reason": "Confirmed false positive after thorough review."
  }
  ```

  ```typescript Javascript theme={null}
  const result = await corsa.cases.bulkUpdateCaseStatus({
    caseIds: ["case-uuid-1", "case-uuid-2"],
    status: "CLOSED_DISMISSED",
    reason: "Confirmed false positive after thorough review.",
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.cases.bulk_update_case_status import _get_kwargs
  from corsa_sdk.models.bulk_update_case_status_dto import BulkUpdateCaseStatusDto

  resp = http.request(**_get_kwargs(
      body=BulkUpdateCaseStatusDto(
          case_ids=["case-uuid-1", "case-uuid-2"],
          status="CLOSED_DISMISSED",
          reason="Confirmed false positive after thorough review.",
      ),
  ))
  result = resp.json()
  ```
</CodeGroup>

***

### Step 13: Bulk Update Case Reviewers

**Endpoint:** `PATCH /v1/cases/bulk/reviewers`

Manage reviewers across multiple cases with three modes: `SET` (replace all), `ADD` (append), or `REMOVE`.

<CodeGroup>
  ```json REST API theme={null}
  PATCH /v1/cases/bulk/reviewers
  Content-Type: application/json

  {
    "caseIds": ["case-uuid-1", "case-uuid-2"],
    "mode": "ADD",
    "reviewersIds": ["reviewer-uuid-1"]
  }
  ```

  ```typescript Javascript theme={null}
  const result = await corsa.cases.bulkUpdateCaseReviewers({
    caseIds: ["case-uuid-1", "case-uuid-2"],
    mode: "ADD",
    reviewersIds: ["reviewer-uuid-1"],
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.cases.bulk_update_case_reviewers import _get_kwargs
  from corsa_sdk.models.bulk_update_case_reviewers_dto import BulkUpdateCaseReviewersDto

  resp = http.request(**_get_kwargs(
      body=BulkUpdateCaseReviewersDto(
          case_ids=["case-uuid-1", "case-uuid-2"],
          mode="ADD",
          reviewers_ids=["reviewer-uuid-1"],
      ),
  ))
  result = resp.json()
  ```
</CodeGroup>

***

### Step 14: Associate Entities with Cases

Link alerts, clients, or transactions to an existing case.

**Associate alerts:** `PUT /v1/cases/{caseId}/alerts`

All case association endpoints accept a plain JSON array of IDs as the request body.

<CodeGroup>
  ```json REST API theme={null}
  PUT /v1/cases/case-uuid/alerts
  Content-Type: application/json

  ["alert-uuid-3"]
  ```

  ```typescript Javascript theme={null}
  await corsa.cases.associateCaseWithAlerts("case-uuid", ["alert-uuid-3"]);
  ```

  ```python Python theme={null}
  from corsa_sdk.api.cases.associate_case_with_alerts import _get_kwargs

  resp = http.request(**_get_kwargs(case_id="case-uuid", body=["alert-uuid-3"]))
  ```
</CodeGroup>

**Associate clients:** `PUT /v1/cases/{caseId}/clients`

<CodeGroup>
  ```json REST API theme={null}
  PUT /v1/cases/case-uuid/clients
  Content-Type: application/json

  ["client-uuid-2"]
  ```

  ```typescript Javascript theme={null}
  await corsa.cases.associateCaseWithClients("case-uuid", ["client-uuid-2"]);
  ```

  ```python Python theme={null}
  from corsa_sdk.api.cases.associate_case_with_clients import _get_kwargs

  resp = http.request(**_get_kwargs(case_id="case-uuid", body=["client-uuid-2"]))
  ```
</CodeGroup>

**Associate transactions:** `PUT /v1/cases/{caseId}/transactions`

<CodeGroup>
  ```json REST API theme={null}
  PUT /v1/cases/case-uuid/transactions
  Content-Type: application/json

  ["transaction-uuid-2"]
  ```

  ```typescript Javascript theme={null}
  await corsa.cases.associateCaseWithTransactions(
    "case-uuid",
    ["transaction-uuid-2"]
  );
  ```

  ```python Python theme={null}
  from corsa_sdk.api.cases.associate_case_with_transactions import _get_kwargs

  resp = http.request(**_get_kwargs(case_id="case-uuid", body=["transaction-uuid-2"]))
  ```
</CodeGroup>

***

## Screening Matches

Screening alerts — those with a category of `SCREENING_SANCTIONS`, `SCREENING_PEP`, or `SCREENING_ADVERSE_MEDIA` — can carry one or more **matches**: the specific list entries or profiles that triggered the alert. The endpoints below let you attach, update, and record decisions on those matches.

<Note>Match endpoints apply only to screening-category alerts. Calls against other alert categories are rejected.</Note>

### Attach Matches to an Alert

**Endpoint:** `POST /v1/alerts/{alertId}/matches`

Add one or more screening matches to an existing alert. Useful when a vendor delivers match data asynchronously after the alert is already created, or when your system appends additional matches.

<CodeGroup>
  ```json REST API theme={null}
  POST /v1/alerts/alert-uuid-123/matches
  Content-Type: application/json

  {
    "matches": [
      {
        "fullName": "John Smith",
        "listName": "OFAC SDN",
        "exposureType": "sanction",
        "confidenceScore": 0.92,
        "country": "IR",
        "vendorName": "Chainalysis",
        "vendorEntityId": "entity-abc-001",
        "sourceUrl": "https://vendor.example.com/profiles/entity-abc-001"
      }
    ]
  }
  ```

  ```typescript Javascript theme={null}
  const result = await corsa.alerts.addScreeningMatches("alert-uuid-123", {
    matches: [
      {
        fullName: "John Smith",
        listName: "OFAC SDN",
        exposureType: "sanction",
        confidenceScore: 0.92,
        country: "IR",
        vendorName: "Chainalysis",
        vendorEntityId: "entity-abc-001",
        sourceUrl: "https://vendor.example.com/profiles/entity-abc-001",
      },
    ],
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.alerts.add_screening_matches import _get_kwargs
  from corsa_sdk.models.add_screening_matches_dto import AddScreeningMatchesDto

  resp = http.request(**_get_kwargs(
      alert_id="alert-uuid-123",
      body=AddScreeningMatchesDto(
          matches=[{
              "fullName": "John Smith",
              "listName": "OFAC SDN",
              "exposureType": "sanction",
              "confidenceScore": 0.92,
              "country": "IR",
              "vendorName": "Chainalysis",
              "vendorEntityId": "entity-abc-001",
          }],
      ),
  ))
  result = resp.json()
  ```
</CodeGroup>

#### Match Fields

| Field                                   | Required | Description                                                            |
| --------------------------------------- | -------- | ---------------------------------------------------------------------- |
| `fullName`                              | No       | Full name of the matched entity                                        |
| `firstName` / `middleName` / `lastName` | No       | Name parts, if available separately                                    |
| `dateOfBirth`                           | No       | Date of birth in ISO or vendor format                                  |
| `age`                                   | No       | Age of the matched entity                                              |
| `gender`                                | No       | Gender of the matched entity                                           |
| `listName`                              | No       | Name of the sanctions or PEP list (e.g. `OFAC SDN`, `UN Consolidated`) |
| `exposureType`                          | No       | Type of exposure: `sanction`, `PEP`, `crime`, etc.                     |
| `confidenceScore`                       | No       | Vendor confidence score, 0–1                                           |
| `country`                               | No       | ISO country code                                                       |
| `aliases`                               | No       | Array of known aliases                                                 |
| `countries`                             | No       | Array of ISO country codes associated with the entity                  |
| `datasets`                              | No       | Source datasets from the vendor                                        |
| `vendorName`                            | No       | Name of the screening vendor                                           |
| `vendorEntityId`                        | No       | Vendor-specific entity identifier                                      |
| `vendorData`                            | No       | Vendor-specific data as key-value pairs                                |
| `sourceUrl`                             | No       | URL to the profile in the vendor's system                              |
| `photoUrl`                              | No       | Photo URL for the matched entity                                       |
| `address`                               | No       | Address of the matched entity                                          |

Up to 100 matches can be attached in a single call.

***

### Update a Match

**Endpoint:** `PATCH /v1/alerts/{alertId}/matches/{matchId}`

Update the profile fields on a match before a decision has been recorded — for example, when the vendor delivers an updated profile with more detail.

<CodeGroup>
  ```json REST API theme={null}
  PATCH /v1/alerts/alert-uuid-123/matches/match-uuid-456
  Content-Type: application/json

  {
    "confidenceScore": 0.98,
    "aliases": ["J. Smith", "Jon Smith"],
    "datasets": ["OFAC", "EU-CONSOLIDATED"]
  }
  ```

  ```typescript Javascript theme={null}
  await corsa.alerts.updateScreeningMatch("alert-uuid-123", "match-uuid-456", {
    confidenceScore: 0.98,
    aliases: ["J. Smith", "Jon Smith"],
    datasets: ["OFAC", "EU-CONSOLIDATED"],
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.alerts.update_screening_match import _get_kwargs
  from corsa_sdk.models.update_screening_match_dto import UpdateScreeningMatchDto

  http.request(**_get_kwargs(
      alert_id="alert-uuid-123",
      match_id="match-uuid-456",
      body=UpdateScreeningMatchDto(
          confidence_score=0.98,
          aliases=["J. Smith", "Jon Smith"],
          datasets=["OFAC", "EU-CONSOLIDATED"],
      ),
  ))
  ```
</CodeGroup>

<Note>Updates are rejected after a decision has been recorded on the match.</Note>

***

### Record a Decision on a Match

**Endpoint:** `POST /v1/alerts/{alertId}/matches/{matchId}/decision`

Record whether a single match is a true positive or a false positive.

<CodeGroup>
  ```json REST API theme={null}
  POST /v1/alerts/alert-uuid-123/matches/match-uuid-456/decision
  Content-Type: application/json

  {
    "status": "FALSE_MATCH",
    "reason": "Name similarity only — different date of birth and nationality",
    "notes": "Reviewed against client passport and corporate registry."
  }
  ```

  ```typescript Javascript theme={null}
  await corsa.alerts.recordScreeningMatchDecision(
    "alert-uuid-123",
    "match-uuid-456",
    {
      status: "FALSE_MATCH",
      reason: "Name similarity only — different date of birth and nationality",
      notes: "Reviewed against client passport and corporate registry.",
    }
  );
  ```

  ```python Python theme={null}
  from corsa_sdk.api.alerts.record_screening_match_decision import _get_kwargs
  from corsa_sdk.models.screening_match_decision_dto import ScreeningMatchDecisionDto

  http.request(**_get_kwargs(
      alert_id="alert-uuid-123",
      match_id="match-uuid-456",
      body=ScreeningMatchDecisionDto(
          status="FALSE_MATCH",
          reason="Name similarity only — different date of birth and nationality",
          notes="Reviewed against client passport and corporate registry.",
      ),
  ))
  ```
</CodeGroup>

#### Decision Fields

| Field    | Required | Description                              |
| -------- | -------- | ---------------------------------------- |
| `status` | Yes      | `TRUE_MATCH` or `FALSE_MATCH`            |
| `reason` | Yes      | Disposition note explaining the decision |
| `notes`  | No       | Additional analyst notes                 |

***

### Record a Bulk Decision

**Endpoint:** `POST /v1/alerts/{alertId}/matches/bulk-decision`

Apply the same decision to multiple matches on a single alert in one request.

<CodeGroup>
  ```json REST API theme={null}
  POST /v1/alerts/alert-uuid-123/matches/bulk-decision
  Content-Type: application/json

  {
    "matchIds": ["match-uuid-456", "match-uuid-789"],
    "status": "FALSE_MATCH",
    "reason": "All matches confirmed false positives after client KYC review",
    "notes": "No adverse findings across all matched profiles."
  }
  ```

  ```typescript Javascript theme={null}
  await corsa.alerts.bulkScreeningMatchDecision("alert-uuid-123", {
    matchIds: ["match-uuid-456", "match-uuid-789"],
    status: "FALSE_MATCH",
    reason: "All matches confirmed false positives after client KYC review",
    notes: "No adverse findings across all matched profiles.",
  });
  ```

  ```python Python theme={null}
  from corsa_sdk.api.alerts.bulk_screening_match_decision import _get_kwargs
  from corsa_sdk.models.bulk_screening_match_decision_dto import BulkScreeningMatchDecisionDto

  http.request(**_get_kwargs(
      alert_id="alert-uuid-123",
      body=BulkScreeningMatchDecisionDto(
          match_ids=["match-uuid-456", "match-uuid-789"],
          status="FALSE_MATCH",
          reason="All matches confirmed false positives after client KYC review",
          notes="No adverse findings across all matched profiles.",
      ),
  ))
  ```
</CodeGroup>

#### Request Fields

| Field      | Required | Description                                      |
| ---------- | -------- | ------------------------------------------------ |
| `matchIds` | Yes      | Array of match IDs to apply the decision to      |
| `status`   | Yes      | `TRUE_MATCH` or `FALSE_MATCH`                    |
| `reason`   | Yes      | Shared disposition note for all selected matches |
| `notes`    | No       | Additional analyst notes                         |

***

### Remove a Match

**Endpoint:** `DELETE /v1/alerts/{alertId}/matches/{matchId}`

Remove a wrongly-attached match — for example, a duplicate delivered by a vendor retry. The client's screening status is recomputed after deletion.

<CodeGroup>
  ```json REST API theme={null}
  DELETE /v1/alerts/alert-uuid-123/matches/match-uuid-456
  ```

  ```typescript Javascript theme={null}
  await corsa.alerts.deleteScreeningMatch("alert-uuid-123", "match-uuid-456");
  ```

  ```python Python theme={null}
  from corsa_sdk.api.alerts.delete_screening_match import _get_kwargs

  http.request(**_get_kwargs(alert_id="alert-uuid-123", match_id="match-uuid-456"))
  ```
</CodeGroup>

<Note>Deletion is rejected if a decision has already been recorded on the match.</Note>

***

## Get Alerts by Entity

**Endpoint:** `GET /v1/alerts/entity/{entityType}/{entityId}`

Retrieve all alerts associated with a specific client, transaction, or case. Use this endpoint instead of relying on embedded `alerts` fields returned on entity responses — those fields are deprecated.

<CodeGroup>
  ```bash REST API theme={null}
  # Alerts for a client
  GET /v1/alerts/entity/client/client-uuid-123

  # Alerts for a transaction
  GET /v1/alerts/entity/transaction/txn-uuid-456

  # Alerts linked to a case
  GET /v1/alerts/entity/case/case-uuid-789

  # Use referenceId instead of Corsa UUID
  GET /v1/alerts/entity/client/USER-12345
  ```

  ```typescript Javascript theme={null}
  // Alerts for a client
  const response = await fetch(
    `${BASE_URL}/v1/alerts/entity/client/client-uuid-123`,
    { headers: { Authorization: `Bearer ${API_TOKEN}:${API_SECRET}` } }
  );
  const { data, meta } = await response.json();

  // Alerts for a transaction
  const txnAlerts = await fetch(
    `${BASE_URL}/v1/alerts/entity/transaction/txn-uuid-456`,
    { headers: { Authorization: `Bearer ${API_TOKEN}:${API_SECRET}` } }
  );
  ```

  ```python Python theme={null}
  import httpx

  resp = httpx.get(
      "https://api.corsa.finance/v1/alerts/entity/client/client-uuid-123",
      headers={"Authorization": f"Bearer {API_TOKEN}:{API_SECRET}"},
      params={"page": 1, "limit": 10},
  )
  alerts = resp.json()
  ```
</CodeGroup>

### Path Parameters

| Parameter    | Required | Description                                                             |
| ------------ | -------- | ----------------------------------------------------------------------- |
| `entityType` | Yes      | The entity type to look up. One of `client`, `transaction`, or `case`.  |
| `entityId`   | Yes      | The Corsa-generated UUID or your external `referenceId` for the entity. |

### Query Parameters

| Parameter | Default          | Description                                                                                                                                        |
| --------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `page`    | `1`              | Page number.                                                                                                                                       |
| `limit`   | `10`             | Records per page. Maximum `100`.                                                                                                                   |
| `sortBy`  | `createdAt:DESC` | Sort field and direction (e.g. `priority:DESC`). Sortable fields: `id`, `referenceId`, `createdAt`, `updatedAt`, `priority`, `status`, `category`. |

### Response

Returns a paginated list of `AlertDto` objects associated with the entity.

***

## What's Next?

<CardGroup cols={2}>
  <Card title="Transaction Monitoring" icon="scale-balanced" href="/transaction-monitoring/index">
    Set up transaction monitoring rules and evaluate transactions.
  </Card>

  <Card title="Manage Attachments" icon="paperclip" href="/api/managing-attachments">
    Upload and link files to alerts, cases, and other entities.
  </Card>
</CardGroup>
