
# Verify again

```
POST /api/kyc/verifications/:id/rerun
```

Asks the applicant to redo a **finished** verification: the same workflow, the same person reference, and a link to send them. Use it when a document has expired, a check failed on something fixable, or your own policy asks for periodic re-verification. This is the API twin of the dashboard's "Verify again" button, and the same operation as sending a verification back with [Decide a verification](https://trust.myaza.co/documentation/api-review-verification/markdown#sending-it-back). All of them run one core.

**The verification keeps its id.** When the applicant resubmits, what they send becomes the next **attempt** of this same verification, not a second verification. What the earlier attempt found is kept rather than overwritten: it is listed under `attempts` on the [result](https://trust.myaza.co/documentation/api-verification-result/markdown#attempts) and shown on the verification's timeline in your dashboard. You hold one id per applicant per check, and your webhook handler keeps updating the record it already has.

Calling it sets the verification's status to `awaiting_resubmission` and sends [`verification.status_updated`](https://trust.myaza.co/documentation/webhooks/markdown#status-changes). Any link sent earlier for the same verification stops working, so the applicant can only ever use the latest one.

**Authentication:** `Authorization: Bearer sk_…` (**secret key required**). The response contains a live verification credential. A publishable key receives `403 secret_key_required`.
**Content type:** `application/json`.
**Production note:** `sk_live_` keys require an [approved business](https://trust.myaza.co/documentation/environments/markdown#production).

## Redo only what failed

By default the applicant walks the whole flow again. Pass `steps` to narrow the redo to specific sections instead: a selfie that did not match does not require the applicant to re-photograph a perfectly good document.

```json
{ "steps": ["liveness"], "message": "Your selfie was too dark to match. Please retake it in good light." }
```

The applicant then walks **only** the ticked steps, with your message shown when they open the link. Everything they are not asked to redo is kept from the earlier attempt. Valid step names:

| Step | What the applicant redoes |
|---|---|
| `id-type` | ID type selection |
| `id-input` | Typing their ID number |
| `document-capture` | Document photos |
| `liveness` | Selfie and liveness |
| `proof-of-address` | Proof of address |
| `nfc` | Chip scan |
| `email-verification` | Email confirmation |
| `phone-verification` | Phone confirmation |
| `business-details` | Business details (KYB) |
| `business-key-people` | Directors and owners (KYB) |
| `business-documents` | Business documents (KYB) |
| `questionnaire` | Questionnaire |

An unknown step name is refused with `400 invalid_steps` rather than ignored. A silently dropped typo would turn a targeted redo into a full one, which is the one failure you could not see happening.

## Email the link

Pass `email` and we send the link to the applicant for you, in your organisation's name. The link is still returned in the response, and `delivery` tells you whether the email went out. Leave `email` out to deliver the link yourself: we hold no contact details for your users.

```json
{ "steps": ["liveness"], "email": "ada@example.com" }
```

## Request body

| Field | Type | Required | Description |
|---|---|---|---|
| `steps` | string[] | no | Sections to redo, from the table above. Absent or empty means the whole flow. |
| `message` | string | no | Shown to the applicant on a narrowed flow, up to 500 characters. Write it for them, not for your logs. |
| `policy` | string | no | `original` runs the workflow version the applicant walked the first time; `latest` runs today's published version. Absent follows the workflow's own setting, which is `original` unless you changed it. |
| `email` | string | no | Send the link to this address as well as returning it. |

## Request

```bash
curl "https://trust.myaza.app/api/kyc/verifications/ver_abc123/rerun" \
  -H "Authorization: Bearer $MYAZA_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "steps": ["liveness"], "email": "ada@example.com" }'
```

## Response `201 Created`

```json
{
  "session": {
    "sessionId": "cmt1gfjce05g547grqbmjsiqf",
    "url": "https://trust.myaza.co/verify/pXk3...",
    "shortCode": "7K9F-2QHM",
    "expiresAt": "2026-08-22T12:00:00.000Z",
    "kind": "individual",
    "workflow": { "id": "wf_AbC123dEf456", "name": "Identity verification", "version": 3 }
  },
  "retryOf": "ver_abc123",
  "attempt": 1,
  "steps": ["liveness"],
  "full": false,
  "delivery": { "emailed": true, "reason": null }
}
```

| Field | Description |
|---|---|
| `session` | The link to send the applicant, the same shape [creating a session](https://trust.myaza.co/documentation/api-create-session/markdown) returns. `session.url` is a credential: whoever opens it verifies as this applicant. |
| `retryOf` | The verification being redone. The applicant's resubmission is recorded against this id. |
| `attempt` | The attempt the verification holds now. The applicant's resubmission becomes attempt `attempt + 1`. |
| `steps` | The plan the link was minted with, in flow order. |
| `full` | `true` when the whole flow will run, which is what absent or empty `steps` produces. |
| `delivery` | When you passed `email`: `{ emailed, reason }`. `emailed: false` with `reason: "send_failed"` means the email could not be sent. The link still works, so send it yourself. Null when you passed no `email`. |

## When the applicant resubmits

Their resubmission is checked like any submission and completes the **same** verification. `verification.completed` (or `verification.failed`) arrives with the same `verificationId` and `attempt` counted up, and [Get verification status](https://trust.myaza.co/documentation/api-verification-status/markdown) reports the new result. You are charged for the steps the applicant redoes, not for the ones they keep.

A link stops working once it has been used, or once something newer replaces it. The applicant sees why when they submit:

| Code | When |
|---|---|
| `verification_in_progress` | A resubmission for this verification is still being checked. |
| `resubmission_superseded` | This verification has already been resubmitted. |
| `resubmission_withdrawn` | The verification was decided, or sent back again, after this link was sent. Only the newest link works. |

## Errors

| Status | Code | Meaning |
|---|---|---|
| 400 | `invalid_input` | The body is malformed, for example `email` is not a valid address. |
| 400 | `invalid_steps` | A step name is not in the table above. The message lists the valid names. |
| 404 | `verification_not_found` | No verification with that id in your organisation and environment. |
| 409 | `verification_in_progress` | The verification has not finished. A pending check may still come back clean. |
| 422 | `no_workflow` | The verification did not run a workflow, so there is no flow to repeat. Start the person again from your own integration. |
| 422 | `workflow_not_available` | The workflow behind the verification is no longer published, so it cannot be redone. |
| 429 | `rate_limited` | Too many sessions started this hour. Try again shortly. |

Verifying again is allowed from **any** finished status, including a passed verification. Re-verifying someone whose document is about to expire is the same operation as retrying a failure.
