Skip to main content

Overview

Generate and send a one-time password (OTP) to a phone number for verification purposes. This endpoint creates a secure OTP and sends it via SMS, returning a request ID that can be used to verify the code later.

Endpoint

curl --request POST \
  "https://sms.lamah.com/api/otp/initiate" \
  --header "Authorization: Bearer YOUR_API_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{
    "lang": "ar",
    "length": 6,
    "expiration": 5,
    "sender": "RealEstate",
    "payment_type": "wallet",
    "receiver": "00218912345678"
  }'

Request Parameters

ParameterTypeRequiredDescription
langstringLanguage for the OTP message: ar or en
lengthintegerLength of the OTP code: 4 or 6
expirationintegerExpiration time in minutes (range: 1–10)
senderstringThe sender ID (up to 11 characters)
payment_typestringPayment method: wallet or subscription
receiverstringThe recipient’s phone number in international format

Parameter Details

The language for the OTP message template.
  • en: English message template
  • ar: Arabic message template
  • Default templates: Pre-defined secure message formats
The number of digits in the OTP code.
  • 4: 4-digit code (e.g., 1234)
  • 6: 6-digit code (e.g., 123456)
  • Security: 6-digit codes provide better security
How long the OTP remains valid.
  • Range: 1 to 10 minutes (inclusive)
  • Guidance: Shorter durations (1–5) increase security; longer durations (6–10) improve UX
The sender ID that will appear on the recipient’s device.
  • Length: Maximum 11 characters
  • Format: Alphanumeric characters only
  • Examples: Lamah, Verify, Security
Specifies how the OTP SMS cost will be charged.
  • wallet: Deduct from your account balance
  • subscription: Use your subscription plan credits
The recipient’s phone number in international format.
  • Format: Must include country code (e.g., +218912345678 or 00218912345678)
  • Validation: Number will be validated before sending

Response

Success Response (200 OK)

{
  "request_id": "8c8a6f2f-9a3b-4d86-9b2c-1e3f8f9c2ab1",
  "cost": 1
}

Response Fields

FieldTypeDescription
request_idstringUUID for this OTP request
costnumberNumber of SMS parts charged for this send

Error Responses

400 Bad Request - Invalid Parameters

{ "message": "The length field must be one of: 4, 6." }

400 Bad Request - Invalid Expiration

{ "message": "The expiration field must be between 1 and 10." }

400 Bad Request - Invalid Phone Number

{ "message": "Invalid phone number" }

401 Unauthorized

{ "message": "Unauthenticated." }

402 Payment Required

{ "message": "Insufficient balance" }

429 Too Many Requests

{ "message": "Too many requests." }

Message Templates

English Template (lang: “en”)

Your verification code is: {CODE}
This code expires in {EXPIRATION} minutes.

Arabic Template (lang: “ar”)

رمز التحقق الخاص بك هو: {CODE}
ينتهي هذا الرمز خلال {EXPIRATION} دقائق.

Rate Limits

OTP Rate Limits: Limited to 10 OTP requests per minute per phone number to prevent abuse.

Rate Limit Details

  • Per phone number: 10 requests per minute
  • Per project: 1000 requests per minute
  • Cooldown period: 60 seconds after rate limit is hit

Security Best Practices

Use 6-digit codes

6-digit codes provide better security than 4-digit codes

Short expiration

Use 1-5 minute expiration for sensitive operations

Rate limiting

Implement client-side rate limiting to prevent abuse

Secure storage

Never log or store the actual OTP codes

Implementation Example

class OTPService {
  constructor(apiToken) {
    this.apiToken = apiToken;
    this.baseUrl = 'https://sms.lamah.com/api';
  }

  async initiateOTP(phoneNumber, options = {}) {
    const defaultOptions = {
      lang: 'en',
      length: 6,
      expiration: 5,
      sender: 'Lamah',
      payment_type: 'wallet'
    };

    const otpData = {
      ...defaultOptions,
      ...options,
      receiver: phoneNumber
    };

    try {
      const response = await fetch(`${this.baseUrl}/otp/initiate`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${this.apiToken}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(otpData)
      });

      if (!response.ok) {
        const error = await response.json();
        throw new Error(`OTP initiation failed: ${error.message}`);
      }

      const result = await response.json();
      
      // Store request_id for verification
      this.storeOTPRequest(phoneNumber, result.request_id);
      
      return result;
      
    } catch (error) {
      console.error('OTP initiation error:', error);
      throw error;
    }
  }

  storeOTPRequest(phoneNumber, requestId) {
    // Store in your database or cache
    // This is just an example using localStorage
    const otpData = {
      requestId,
      phoneNumber
    };
    localStorage.setItem(`otp_${phoneNumber}`, JSON.stringify(otpData));
  }

  getStoredOTPRequest(phoneNumber) {
    const stored = localStorage.getItem(`otp_${phoneNumber}`);
    return stored ? JSON.parse(stored) : null;
  }
}

// Usage
const otpService = new OTPService('YOUR_API_TOKEN');

const sendOTP = async (phoneNumber) => {
  try {
    const result = await otpService.initiateOTP(phoneNumber, {
      length: 6,
      expiration: 5,
      lang: 'en'
    });
    
    console.log('OTP sent successfully:', result.request_id);
    return result;
    
  } catch (error) {
    console.error('Failed to send OTP:', error.message);
    return null;
  }
};

Next Steps

After initiating an OTP, you’ll need to verify the code that the user receives. Use the Verify OTP endpoint with the request_id returned from this endpoint.

Common Use Cases

User Registration

Verify phone numbers during account creation

Login Verification

Two-factor authentication for secure login

Password Reset

Verify identity before allowing password changes

Transaction Confirmation

Confirm high-value transactions or sensitive operations