---
title: "Verify users with OTP"
description: "Verify an SMS one-time password and authorize only a passing attempt."
canonical: "https://studio.inttegro.com/guides/verify-with-otp"
format: inttegro-machine-docs/v1
language: "Java"
sdk_version: "v8.3.0"
reader_profile: optional
reader_manifest: "https://studio.inttegro.com/machine/java/readers/index.json"
reader_identification: "Optional: declare your client only if known and your current-session capabilities; use reader_manifest for supplemental recommendations."
preamble_estimated_tokens: 359
model_token_report: "https://studio.inttegro.com/machine/token-report.json"
preamble_questions: 5
preamble_source: "curated"
recommended_mcp_tools: ["get_integration_guide","check_integration_readiness"]
estimated_tokens: 1610
token_estimate_method: "utf8_bytes_divided_by_4"
---

## Machine preamble

**Summary:** Bind an SMS verification attempt to its initiated transaction and authorize the protected action only when the returned verdict passes.

### Five questions

#### Q1. What must the server retain after initiation?

Persist the returned OTP transaction ID with the pending action and recipient. [OTP initiation](https://studio.inttegro.com/machine/java/api/otps.md#initiate-otp-transaction) may report delivery still pending; that is not a verification result.

#### Q2. What should be submitted for verification?

Submit the transaction ID, the same international phone number, and the token entered by the user. Keep the token out of logs, analytics, and model context.

#### Q3. Does HTTP 200 mean the code matched?

No. It means the attempt was recorded. The protected action may continue only when the [verification verdict](https://studio.inttegro.com/machine/java/api/otps.md#verify-otp) is pass.

#### Q4. Can delivery state grant access?

No. Delivery and verification are separate. A sent SMS or pending-verification transaction does not establish that the customer supplied the correct token.

#### Q5. Should an MCP client submit or check the OTP?

No. The current [MCP catalog](https://studio.inttegro.com/machine/java/inttegro-mcp/tools.md) does not expose OTP initiation or verification. Keep submission and verdict checks in the trusted backend; MCP may help with adjacent context only.

## Document content

# Verify users with OTP

Use a one-time password when you need to confirm that a user controls an international phone number. Inttegro sends the token by SMS and records each verification attempt; your application must inspect the attempt verdict before granting access.

> **Note:**
>
> The [MCP tool catalog](https://studio.inttegro.com/machine/java/inttegro-mcp/tools.md) does not currently expose OTP
> initiation or verification. Keep OTP submission and verdict checks in your
> trusted backend; use MCP for adjacent customer or order investigation only
> when that context is relevant.

## Prerequisites

- The user's phone number in international format
- A server-side place to associate the typed OTP transaction ID with the pending action

## Initiate the SMS verification

Call [Initiate OTP transaction](https://studio.inttegro.com/machine/java/api/otps.md#initiate-otp-transaction) with `recipient(…)`, `serviceName(…)`, and `tokenSize(…)`. Set `purpose(…)` to `sign_in` so the message explains why the code was sent. The current API requires a token size from 5 through 10. The service name must be 2-20 characters; an optional sender must be 3-12 characters. Validity defaults to 10 minutes and can be set from 3 through 10,080 minutes.

Persist the returned ID in the form `ot_<TRANSACTION_ID>`. A transaction can be `"pending_delivery"` before transmission details are available and `"pending_verification"` after the SMS is sent.

## Verify the submitted token

Submit the transaction ID, the same international phone number, and the token entered by the user. An HTTP 200 response means the attempt was recorded, not that the token matched. Continue only when [`verificationAttempt(…).result(…).verdict(…)`](https://java.inttegro.dev/v8.3.0/com/inttegro/otp/OtpVerification.html) is `"pass"`.

```java
import com.inttegro.Client;
import com.inttegro.RequestMeta;
import com.inttegro.otp.InitiateOtpParams;
import com.inttegro.otp.OtpAlphabetType;
import com.inttegro.otp.OtpPurpose;
import com.inttegro.otp.OtpVerificationVerdict;
import com.inttegro.otp.VerifyOtpParams;

public class Example {
  public static void main(String[] args) throws Exception {
    var client = new Client(System.getenv("INTTEGRO_API_KEY"));
    var recipient = "<USER_PHONE_E164>";
    var otpCodeFromUser = "<OTP_ENTERED_BY_USER>";

    var initiated = client.otp().initiate(
        InitiateOtpParams.builder()
            .requestMeta(RequestMeta.withIdempotencyKey("verify-user-123"))
            .recipient(recipient)
            .purpose(OtpPurpose.SIGN_IN)
            .sender("MyApp")
            .serviceName("MyApp")
            .tokenAlphabetType(OtpAlphabetType.NUMERIC)
            .tokenSize(6)
            .build()
    );
    var verified = client.otp().verify(
        VerifyOtpParams.builder()
            .recipient(recipient)
            .token(otpCodeFromUser)
            .transactionId(initiated.id)
            .build()
    );

    if (verified.verificationAttempt.result.verdict != OtpVerificationVerdict.PASS) {
      throw new IllegalStateException("The supplied OTP did not match");
    }
  }
}
```

Do not log the submitted token or verification response body. If the verdict is `"fail"`, keep the protected action pending and let the user retry only within your attempt policy. Use [Lookup OTP transaction](https://studio.inttegro.com/machine/java/api/otps.md#lookup-otp-transaction) to refresh the transaction state, or [Cancel OTP transaction](https://studio.inttegro.com/machine/java/api/otps.md#cancel-otp-transaction) when the flow is abandoned.

## Related resources

- [Initiate OTP transaction](https://studio.inttegro.com/machine/java/api/otps.md#initiate-otp-transaction) - Complete initiation contract
- [Verify OTP](https://studio.inttegro.com/machine/java/api/otps.md#verify-otp) - Verification request and attempt result
- [Lookup OTP transaction](https://studio.inttegro.com/machine/java/api/otps.md#lookup-otp-transaction) - Current transaction status
- [Cancel OTP transaction](https://studio.inttegro.com/machine/java/api/otps.md#cancel-otp-transaction) - Invalidate an active transaction
