
# Delete, expire & cancel

Four server-to-server endpoints for tidying your own records: delete a verification or an unfinished attempt, delete a spot check, delete a face check, and end a live verification session before its clock runs out.

**Authentication:** `Authorization: Bearer sk_…` (**secret key required**). A publishable key receives `403 secret_key_required`. Removing records is a backend act, and a publishable key ships in a browser.
**Content type:** `application/json`.

## What a delete does

Deleting is **soft**. The record leaves every surface your organisation can read: the dashboard, the [list](https://trust.myaza.co/documentation/api-list-verifications/markdown), the [result](https://trust.myaza.co/documentation/api-verification-result/markdown) and [status](https://trust.myaza.co/documentation/api-verification-status/markdown) endpoints, the media URLs in earlier webhooks, and your exports. Your analytics stop counting it. Nothing is refunded, because the work it describes was done.

The record is not destroyed. Myaza keeps it, marked as deleted, so a compliance history cannot be silently rewritten. **A deleted record cannot be restored through the API.** If something was deleted by mistake, contact support; a restore arrives as a `verification.restored` or `entity.restored` [webhook](https://trust.myaza.co/documentation/webhooks/markdown).

A verification that is still `processing` cannot be deleted. Its checks may still come back, and a system error may still refund the charge. Wait for the result.

## Delete a verification or attempt

```
DELETE /api/kyc/verifications/:id
```

`:id` is the id you already hold. A verification adopts its session's id, so this works from the moment a session is created: a finished verification is deleted, and a session nobody has submitted is deleted as an attempt.

```bash
curl -X DELETE "https://trust.myaza.app/api/kyc/verifications/ver_abc123" \
  -H "Authorization: Bearer $MYAZA_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Test data from the integration rehearsal" }'
```

| Field | Type | Required | Description |
|---|---|---|---|
| `reason` | string | no | Up to 500 characters, kept in your organisation's audit log. It is never sent to your webhook. |

### Response `200 OK`

```json
{
  "verificationId": "ver_abc123",
  "kind": "verification",
  "deleted": true,
  "deletedAt": "2026-09-05T10:12:00.000Z"
}
```

`kind` is `verification` for a submitted record and `attempt` for a session that never submitted. Your endpoints receive `verification.deleted` with the same two fields.

## Delete a spot check

```
DELETE /api/kyc/checks/individual/:id
DELETE /api/kyc/checks/business/:id
```

The same body and the same soft-delete semantics, for the [spot checks](https://trust.myaza.co/documentation/api-spot-checks/markdown) run server to server or from the dashboard. Spot checks never fire webhooks, so nothing is sent when one is deleted.

```json
{ "id": "chk_9f1…", "deleted": true, "deletedAt": "2026-09-05T10:12:00.000Z" }
```

## Delete a face check

```
DELETE /api/kyc/face/checks/:id
```

`:id` is the `faceCheck.id` returned by [`POST /api/kyc/face/compare`](https://trust.myaza.co/documentation/api-face-match/markdown) or listed by `GET /api/kyc/face/checks`. A face check is synchronous, so there is no processing state to wait for: any check you can read can be deleted. The photos stay under their existing retention policy, and nothing is refunded.

```bash
curl -X DELETE "https://trust.myaza.app/api/kyc/face/checks/fc_abc123" \
  -H "Authorization: Bearer $MYAZA_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Uploaded the wrong photo pair" }'
```

| Field | Type | Required | Description |
|---|---|---|---|
| `reason` | string | no | Up to 500 characters, kept in your organisation's audit log. |

### Response `200 OK`

```json
{
  "id": "fc_abc123",
  "deleted": true,
  "deletedAt": "2026-09-05T10:12:00.000Z"
}
```

Face checks never send webhooks, so no event follows. A deleted check disappears from `GET /api/kyc/face/checks`, cannot be re-read at `/checks/:id`, and is no longer offered as a rerun source in the dashboard.

## Expire a session

```
POST /api/kyc/sessions/:sessionId/expire
```

Ends a live session early. The link stops working at once, the applicant cannot continue, and anything they had entered is discarded. Your endpoints receive `session.expired` with the next `sequence` number, exactly as when a session times out on its own, so nothing about your webhook handling changes. Use it when a link went to the wrong person, or when you have replaced it with a new one.

```bash
curl -X POST "https://trust.myaza.app/api/kyc/sessions/cmt1gfjce05g547grqbmjsiqf/expire" \
  -H "Authorization: Bearer $MYAZA_SECRET_KEY"
```

### Response `200 OK`

```json
{
  "sessionId": "cmt1gfjce05g547grqbmjsiqf",
  "status": "expired",
  "changed": true,
  "expiresAt": "2026-09-05T10:12:00.000Z"
}
```

`changed` is `false` when the session had already ended on its own; the call is safe to repeat. A session the applicant has submitted cannot be expired, because it has a verification now.

## Cancel a session or a processing verification

```
POST /api/kyc/sessions/:id/cancel
POST /api/kyc/sessions/:id/uncancel
```

Stops a verification midway, and takes that back. The `:id` is either a session's or a verification's (a verification keeps its session's id), and either can be cancelled:

- **A session the applicant has not submitted.** They can no longer continue: the hosted link, the SDK and `/session/start` answer `409 session_cancelled` until you uncancel it. What they had entered is kept, so after an uncancel they carry on where they left off. Your endpoints receive `session.cancelled`, then `session.uncancelled`.
- **A verification that is still processing.** That is one that is queued, waiting for credit, or holding its decision on screening, key people or an address check. Nothing further runs on it until you uncancel it, and then it carries on from where it stopped. Your endpoints receive `verification.status_updated` with `status: "cancelled"`, and again when it is uncancelled.

While a person's latest session for a workflow is cancelled, the SDK does not start them over either. Uncancel it, or create a new session for them, to let them try again.

**Money.** Once any check has run (a registry lookup, a document read, a government lookup, the device analysis), cancelling refunds nothing. If nothing has run yet, the amount reserved for it is refunded. Uncancelling never charges twice.

Optional body for a cancel: `{ "reason": "Customer asked us to stop" }` (up to 500 characters). It goes to your audit log and is never sent to a webhook.

```bash
curl -X POST "https://trust.myaza.app/api/kyc/sessions/cmt1gfjce05g547grqbmjsiqf/cancel" \
  -H "Authorization: Bearer $MYAZA_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Customer asked us to stop" }'
```

### Response `200 OK`

```json
{
  "id": "cmt1gfjce05g547grqbmjsiqf",
  "kind": "verification",
  "status": "cancelled",
  "previousStatus": "processing",
  "changed": true,
  "refunded": false
}
```

`kind` is `attempt` for a session that had not submitted and `verification` for one that had. `changed` is `false` when it was already cancelled; the call is safe to repeat. An uncancel answers the same shape, with the status it went back to.

## Errors

| Status | Code | Meaning |
|---|---|---|
| 400 | `invalid_input` | The reason is longer than 500 characters. |
| 404 | `verification_not_found` / `not_found` / `session_not_found` | Nothing with that id in your organisation and environment. A record that is already deleted answers the same way. |
| 409 | `verification_in_progress` / `check_in_progress` | Still processing. Wait for the result before deleting it. |
| 409 | `session_already_submitted` | The applicant finished; there is nothing left to expire. |
| 409 | `verification_running` | Cancel only: its checks are running right now. They finish within a minute or two; try again then. |
| 409 | `not_processing` | Cancel only: it has finished, or the session has already ended. |
| 409 | `not_cancelled` | Uncancel only: it is not cancelled. |
| 409 | `session_expired` | Uncancel only: the session ran out of time while it was cancelled. Create a new session instead. |
| 403 | `secret_key_required` | A publishable key was used. |
