Report a verification#
Submit the code the user received by SMS or phone call. The endpoint identifies the
verification by the id returned when it was started and checks the submitted code against
that verification.
A correct value changes a pending verification to verified. An incorrect value can leave
the verification available for another attempt until the attempt limit is reached. Reporting
a verification that has already reached a terminal state does not reopen or change it.
To submit a value without storing the verification id, use
Report a verification by number.
Request#
HTTP method: PATCH (PUT is accepted as an alias)
Path: /api/v1/verifications/{id}
Path parameters#
Name |
Type |
Description |
|---|---|---|
|
|
Verification identifier (UUID) returned by Start a verification. |
Request body#
The request body contains a top-level data object. Use code for both sms and
callout.
Field |
Type |
Required |
Description |
|---|---|---|---|
|
|
Yes |
Must match the method used to start the verification. Supported values are |
|
|
Yes |
The code the user received by SMS or phone call. |
Response#
When the API accepts the report request, it returns 200 OK with the
verification object under a top-level data
key. Authentication, lookup, and validation errors return an errors array.
The following table lists the HTTP status codes returned by this endpoint:
Status |
Meaning |
|---|---|
|
The report was processed. Inspect the returned |
|
Authentication failed, credentials are missing or invalid, or the authentication mode is below the minimum configured for the OTP application. |
|
No verification with the specified |
|
The submitted report could not be accepted. This includes an incorrect code or a
mismatched |
A correct code returns 200 OK with status verified. An incorrect code returns
422 Unprocessable Content with code_invalid. The verification remains available for
another report until the attempt limit is reached. After three unsuccessful reports, it
becomes failed with error_code too_many_attempts.
If the challenge has not yet been dispatched, the API can return 422 Unprocessable
Content with not_ready_to_report. Submit the value again after the challenge has been
sent or the call has been placed.
See Errors and status codes for the error response structure and available error codes.
Warning
Each report can consume one of the three allowed attempts. Do not automatically retry a report after a timeout or another ambiguous network failure. Check the verification status before deciding whether the user should submit the value again.
Examples#
The REST API examples use HTTP Basic authentication. See REST API 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, Python, Node.js, PHP, iOS, Android, React Native, and Dart SDK pages.
The identifiers, expiration times, fees, and codes shown in the examples are illustrative.
REST API#
Send a PATCH request with the verification id and the value reported by the user. A
correct value returns the updated verification with status verified.
http
PATCH /api/v1/verifications/0f9c8b7a-1e2d-4c3b-9a8f-7e6d5c4b3a21 HTTP/1.1
Host: verification.didww.com
Content-Type: application/json
Accept: application/json
Authorization: Basic eW91cl9hcHBfa2V5OnlvdXJfYXBwX3NlY3JldA==
{
"data": {
"delivery_method": "sms",
"code": "123456"
}
}
curl
curl -i -X PATCH https://verification.didww.com/api/v1/verifications/0f9c8b7a-1e2d-4c3b-9a8f-7e6d5c4b3a21 -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"data": {"code": "123456", "delivery_method": "sms"}}' --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": "verified",
"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
}
}
}
http
PATCH /api/v1/verifications/2b3c4d5e-6f70-4b3c-9d0e-1f2a3b4c5d6e HTTP/1.1
Host: verification.didww.com
Content-Type: application/json
Accept: application/json
Authorization: Basic eW91cl9hcHBfa2V5OnlvdXJfYXBwX3NlY3JldA==
{
"data": {
"delivery_method": "callout",
"code": "123456"
}
}
curl
curl -i -X PATCH https://verification.didww.com/api/v1/verifications/2b3c4d5e-6f70-4b3c-9d0e-1f2a3b4c5d6e -H "Accept: application/json" -H "Content-Type: application/json" --data-raw '{"data": {"code": "123456", "delivery_method": "callout"}}' --user your_app_key:your_app_secret
response
HTTP/1.1 200 OK
Content-Type: application/json
{
"data": {
"id": "2b3c4d5e-6f70-4b3c-9d0e-1f2a3b4c5d6e",
"destination": "4915112345678",
"delivery_method": "callout",
"fee": "0.08",
"status": "verified",
"error_code": null,
"error_detail": null,
"expires_at": "2026-07-15T10:05:00.000Z",
"callout": {
"language": "de-DE",
"code_length": 6
}
}
}
Ruby SDK#
The Ruby SDK sends a PATCH request when report_verification(...) is called and returns
the updated verification object.
result = client.report_verification(
verification.id,
delivery_method: "sms",
code: "123456"
)
result.status # => "verified"
result.verified? # => true
result = client.report_verification(
verification.id,
delivery_method: "callout",
code: "123456"
)
result.status # => "verified"
result.verified? # => true
Python SDK#
The Python SDK sends a PATCH request when report_verification(...) is called and
returns the updated Verification.
result = client.report_verification(
verification.id,
delivery_method="sms",
code="123456",
)
result.status # "verified"
result = client.report_verification(
verification.id,
delivery_method="callout",
code="123456",
)
result.status # "verified"
An incorrect code raises DidwwValidationError with code_invalid, as described above:
the verification stays pending and can be reported again. Once three attempts are used,
the next report returns a Verification whose status is failed. A report is never
retried by the SDK: each one consumes an attempt.
Node.js SDK#
The Node.js SDK sends a PATCH request when reportVerification(...) is called and
returns the updated verification.
const result = await client.reportVerification(verification.id, {
deliveryMethod: 'sms',
code: '123456',
});
result.status; // 'verified'
const result = await client.reportVerification(verification.id, {
deliveryMethod: 'callout',
code: '123456',
});
result.status; // 'verified'
If a report times out after it may have reached the API, call getVerification rather than
sending it again.
PHP SDK#
The PHP SDK sends a PATCH request when reportVerification(...) is called and returns
the updated Verification.
$result = $client->reportVerification($verification->id, DeliveryMethod::Sms, '123456');
$result->status; // "verified"
$result = $client->reportVerification($verification->id, DeliveryMethod::Callout, '123456');
$result->status; // "verified"
An incorrect code throws ValidationException with code_invalid, as described above:
the verification stays pending and can be reported again. Once three attempts are used,
the next report returns a Verification whose status is failed. A report is never
retried by the SDK: each one consumes an attempt.
iOS SDK#
The iOS SDK sends a PUT request when verify(...) is called and returns a
VerificationResult containing the updated state. It selects the delivery method from the
Verification returned by start(...) and rejects a code that does not match that method
before sending a request.
let result = try await client.verify(
verification,
code: "123456"
)
result.status // .verified
let result = try await client.verify(
verification,
code: "123456"
)
result.status // .verified
Android SDK#
The Android SDK reports through the VerificationHandle returned by start(...). The
following examples assume that handle.states is already being collected exactly once.
Call submit(...) with the code. The handle reports it for the selected delivery method.
handle.submit("123456")
handle.submit("123456")
The existing states collection emits VerificationState.Submitting while the report is
in progress. A correct value then emits VerificationState.Verified. If the API rejects the
value but allows another attempt, the flow returns to VerificationState.AwaitingInput with
lastError set. A terminal outcome emits VerificationState.Failed or
VerificationState.Expired.
Dart SDK#
The Dart SDK sends a PATCH request when reportVerification(...) is called. The
reported value is wrapped in a ReportValue, and the SDK throws
ChannelMismatchException before sending anything when the value does not suit the
delivery method.
final finished = await client.reportVerification(
started.id,
deliveryMethod: DeliveryMethod.sms,
value: const ReportValue.code('123456'),
);
finished.knownStatus; // VerificationStatus.verified
final finished = await client.reportVerification(
started.id,
deliveryMethod: DeliveryMethod.callout,
value: const ReportValue.code('123456'),
);
finished.knownStatus; // VerificationStatus.verified
With VerificationSession, call session.submit(code) instead and read the result from
the state stream.
React Native SDK#
The React Native SDK reports through the useVerification() controller created when the
verification was started. The controller selects the delivery method from the active
verification, so the call is the same for both channels:
controller.submit('123456');
state.kind moves to 'submitting', then to 'verified'. If the API rejects the code
but allows another attempt, it returns to 'awaitingInput' with the error attached. On
Android a code captured from the SMS is handed to you as state.kind === 'captured'; it is
not submitted for you.