# Get verification status

Retrieve the current state of a verification by using the `id` returned when the
verification was started. Use this endpoint to determine whether the verification is still
pending or has reached a final outcome.

The request only reads the verification. It does not change its state or consume a report
attempt. To retrieve a verification without storing its `id`, use
[Get verification status by number](get-verification-status-by-number.html#otp-verification-api-status-by-number).

## Request

HTTP method: `GET`

Path: `/api/v1/verifications/{id}`

### Path parameters

| Name | Type | Description |
| --- | --- | --- |
| `id` | `string` | Verification identifier (UUID) returned by [Start a verification](start-verification.html#otp-verification-api-start). |

## Response

When the verification is found, the endpoint returns `200 OK` with the
[verification object](index.html#otp-verification-object-reference) under a top-level `data`
key. Authentication and lookup errors return an `errors` array.

The following table lists the HTTP status codes returned by this endpoint:

| Status | Meaning |
| --- | --- |
| `200 OK` | The verification was found. Inspect `status`, `error_code`, and `error_detail` to determine its current state and outcome. |
| `401 Unauthorized` | Authentication failed, credentials are missing or invalid, or the authentication mode is below the minimum configured for the OTP application. |
| `404 Not Found` | No verification with the specified `id` exists for the OTP application, or it passed the [retention period](#otp-verification-retention). |

See [Errors and status codes](errors.html#otp-verification-api-errors) for the error response
structure and available error codes.

### Interpreting the status

The `status` field describes the verification state when the request is processed:

| Status | Meaning |
| --- | --- |
| `pending` | The verification is active and has not reached a final outcome. The API may still be delivering the challenge or waiting for the user to submit a code. |
| `verified` | The submitted code was accepted, and the phone number was verified. |
| `failed` | The verification could not be completed. Inspect `error_code` for the reason. |
| `expired` | The verification expired before a correct value was accepted. |
| `denied` | The verification was rejected before challenge delivery. Inspect `error_code` for the reason. |

Only `pending` can transition to another status. Stop checking the verification after it
becomes `verified`, `failed`, `expired`, or `denied`.

A `pending` response is a snapshot of the verification at the time of the request. Send
another status request later when your application needs the latest state.

### Retention

A verification stays readable for at least 24 hours after it reaches a final status. Once that
period passes, the verification is removed, and both this endpoint and
[Get verification status by number](get-verification-status-by-number.html#otp-verification-api-status-by-number) answer
`404 Not Found`. Store the outcome in your own system if your application needs it later.

## Examples

The REST API example uses HTTP Basic authentication. See
[REST API authentication](../authentication.html#otp-verification-authentication) for credential and header
requirements.

The SDK examples assume that the corresponding SDK is installed and initialized, and that
the verification returned by the start operation is available. See the
[Ruby](../sdks/ruby.html#otp-verification-sdk-ruby),
[Python](../sdks/python.html#otp-verification-sdk-python),
[Node.js](../sdks/node.html#otp-verification-sdk-node),
[PHP](../sdks/php.html#otp-verification-sdk-php),
[iOS](../sdks/ios.html#otp-verification-sdk-ios),
[Android](../sdks/android.html#otp-verification-sdk-android),
[React Native](../sdks/react-native.html#otp-verification-sdk-react-native), and
[Dart](../sdks/dart.html#otp-verification-sdk-dart) SDK pages.

The identifier, expiration time, and fee shown in the examples are illustrative.

### REST API

Send a `GET` request containing the verification `id` in the path. The following
example returns an active SMS verification with `status` `pending`:

http

```
GET /api/v1/verifications/0f9c8b7a-1e2d-4c3b-9a8f-7e6d5c4b3a21 HTTP/1.1
Host: verification.didww.com
Accept: application/json
Authorization: Basic eW91cl9hcHBfa2V5OnlvdXJfYXBwX3NlY3JldA==
```

curl

```
curl -i -X GET https://verification.didww.com/api/v1/verifications/0f9c8b7a-1e2d-4c3b-9a8f-7e6d5c4b3a21 -H "Accept: application/json" --user your_app_key:your_app_secret
```

response

```
HTTP/1.1 200 OK
Content-Type: application/json

{
  "data": {
    "id": "0f9c8b7a-1e2d-4c3b-9a8f-7e6d5c4b3a21",
    "destination": "4915112345678",
    "delivery_method": "sms",
    "fee": "0.06",
    "status": "pending",
    "error_code": null,
    "error_detail": null,
    "expires_at": "2026-07-15T10:05:00.000Z",
    "sms": {
      "template": "Your code is {{CODE}}",
      "language": "en-US",
      "interception_timeout": 300,
      "code_length": 6
    }
  }
}
```

The request is the same for every delivery method. Phone call responses do not include an
`sms` object.

### Ruby SDK

The Ruby SDK sends a `GET` request when `get_verification(...)` is called and returns a
verification object containing the current state.

```
verification = client.get_verification(
  "0f9c8b7a-1e2d-4c3b-9a8f-7e6d5c4b3a21"
)

verification.status    # => "pending"
verification.pending?  # => true
verification.finished? # => false
```

Use `finished?` to stop checking after the verification reaches a final status.

### Python SDK

The Python SDK sends a `GET` request when `get_verification(...)` is called and returns a
`Verification` containing the current state.

```
verification = client.get_verification(
    "0f9c8b7a-1e2d-4c3b-9a8f-7e6d5c4b3a21"
)

verification.status       # "pending"
verification.is_finished  # False
```

Use `is_finished` to stop polling. It is derived from `status` rather than from a list of
terminal values, so a status added after the SDK was released is treated as finished rather
than polled forever. Reads are the only requests the SDK retries.

### Node.js SDK

The Node.js SDK sends a `GET` request when `getVerification(...)` is called and returns
the decoded verification.

```
const current = await client.getVerification(
  '0f9c8b7a-1e2d-4c3b-9a8f-7e6d5c4b3a21',
);

current.status; // 'pending'
```

`getVerification` rejects with a `404` `ApiError` once the verification has passed the
[retention period](#otp-verification-retention).

### PHP SDK

The PHP SDK sends a `GET` request when `getVerification(...)` is called and returns a
`Verification` containing the current state.

```
$verification = $client->getVerification('0f9c8b7a-1e2d-4c3b-9a8f-7e6d5c4b3a21');

$verification->status;       // "pending"
$verification->isFinished(); // false
```

Use `isFinished()` to stop polling. It is `true` for every status other than `pending`,
so a status added after the SDK was released is treated as finished rather than polled
forever. Reads are the only requests the SDK retries.

### iOS SDK

The iOS SDK sends a `GET` request when `status(...)` is called and returns a
`VerificationResult` containing the current state.

```
let current = try await client.status(verification)

current.status            // .pending
current.status.isTerminal // false
```

Use `status.isTerminal` to stop checking after the verification reaches a final status.

### Android SDK

The Android SDK does not provide a separate `status()` method and does not poll this
endpoint. For a verification started through the SDK, continue using the single
`handle.states` collection created for that verification. The flow reports the states
produced by the active SDK verification process:

```
viewModelScope.launch {
    handle.states.collect { state ->
        when (state) {
            is VerificationState.AwaitingInput ->
                println("pending")
            is VerificationState.Verified ->
                println("verified")
            is VerificationState.Failed ->
                println("failed: ${state.reason}")
            VerificationState.Expired ->
                println("expired")
            is VerificationState.Denied ->
                println("denied")
            is VerificationState.SetupError ->
                println("denied: ${state.code}")
            else -> Unit
        }
    }
}
```

`VerificationState.AwaitingInput` corresponds to API status `pending`. `Verified`,
`Expired`, and `Denied` correspond to the matching final API statuses. `Failed` can
represent either API status `failed` or an SDK-side failure; inspect `state.reason` to
distinguish them. `SetupError` identifies an OTP application configuration problem.

When an Android application needs an explicit status refresh outside the active handle, call
this REST endpoint from your backend.

### Dart SDK

The Dart SDK sends a `GET` request when `getVerification(...)` is called and returns a
`Verification` containing the current state.

```
final current = await client.getVerification(
  '0f9c8b7a-1e2d-4c3b-9a8f-7e6d5c4b3a21',
);

current.knownStatus; // VerificationStatus.pending
current.isFinished;  // false
```

`knownStatus` is the typed value and is `null` for a status this release does not know;
`status` is always the raw string. Use `isFinished` to stop polling.

A Flutter screen driven by `VerificationSession` should read `session.state` or listen to
`session.states` rather than calling this endpoint on a timer.

### React Native SDK

The React Native SDK does not poll this endpoint. The `useVerification()` controller
already holds the current state, so render from it:

```
switch (controller.state.kind) {
  case 'awaitingInput':
    return <Text>Pending</Text>;
  case 'verified':
    return <Text>Verified</Text>;
  case 'denied':
  case 'expired':
  case 'failed':
    return <Text>Not verified</Text>;
  default:
    return <Text>Please wait...</Text>;
}
```

Where an explicit refresh is needed outside the controller, call `getVerification` on the
`VerificationClient` from `@didww/verification-core`, which the package installs.

On this page
