API Reference#

This page provides a complete reference for the core APIs, services, and models in django-phone-verify.

Services#

PhoneVerificationService#

class phone_verify.services.PhoneVerificationService(phone_number, backend=None)#

Main service class for sending and managing phone verification messages.

Parameters:
  • phone_number (str) – The phone number to verify (E.164 format recommended)

  • backend (BaseBackend or None) – Optional backend instance. If None, uses the configured backend from settings

Methods:

send_verification(number, security_code, context=None)#

Send a verification SMS to the specified phone number.

Parameters:
  • number (str) – Recipient phone number

  • security_code (str) – The generated security code to send

  • context (dict) – Optional context for custom message formatting (e.g., {"username": "John"})

Raises:

Backend-specific exception (e.g., TwilioRestException)

Example:

from phone_verify.services import PhoneVerificationService

service = PhoneVerificationService(phone_number="+1234567890")
service.send_verification(
    number="+1234567890",
    security_code="123456",
    context={"username": "Alice"}
)
phone_verify.services.send_security_code_and_generate_session_token(phone_number)#

High-level function that generates a security code, creates a session token, and sends the SMS.

Parameters:

phone_number (str) – The phone number to send the code to

Returns:

The generated session token (JWT)

Return type:

str

Example:

from phone_verify.services import send_security_code_and_generate_session_token

session_token = send_security_code_and_generate_session_token("+1234567890")
# Returns: "eyJ0eXAiOiJKV1QiLCJhbGc..."

Backends#

BaseBackend#

class phone_verify.backends.base.BaseBackend(**settings)#

Abstract base class for all SMS backends. Extend this to create custom backends.

Class Attributes:

  • SECURITY_CODE_VALID = 0 - Code is valid and verified

  • SECURITY_CODE_INVALID = 1 - Code doesn’t exist or is incorrect

  • SECURITY_CODE_EXPIRED = 2 - Code has expired

  • SECURITY_CODE_VERIFIED = 3 - Code already used (when VERIFY_SECURITY_CODE_ONLY_ONCE=True)

  • SESSION_TOKEN_INVALID = 4 - Session token doesn’t match

Abstract Methods (must be implemented):

abstract send_sms(number, message)#

Send a single SMS message.

Parameters:
  • number (str) – Recipient phone number

  • message (str) – Message content

abstract send_bulk_sms(numbers, message)#

Send an SMS to multiple recipients.

Parameters:
  • numbers (list) – List of recipient phone numbers

  • message (str) – Message content

Concrete Methods:

classmethod generate_security_code()#

Generate a random numeric security code based on TOKEN_LENGTH setting.

Returns:

Random numeric string (e.g., “123456”)

Return type:

str

classmethod generate_session_token(phone_number)#

Generate a unique JWT session token for the phone number.

Parameters:

phone_number (str) – Phone number to encode

Returns:

JWT token

Return type:

str

create_security_code_and_session_token(number)#

Create a security code and session token, storing them in the database.

Parameters:

number (str) – Phone number

Returns:

Tuple of (security_code, session_token)

Return type:

tuple

validate_security_code(security_code, phone_number, session_token)#

Validate a security code for a phone number.

Parameters:
  • security_code (str) – The code to validate

  • phone_number (str) – Phone number to verify

  • session_token (str) – Session token from registration

Returns:

Tuple of (SMSVerification object or None, status code)

Return type:

tuple

generate_message(security_code, context=None)#

Optional method to customize message generation. Return None to use default.

Parameters:
  • security_code (str) – The generated code

  • context (dict) – Optional runtime context

Returns:

Custom message string or None

Return type:

str or None

Example:

def generate_message(self, security_code, context=None):
    username = context.get("username", "User") if context else "User"
    return f"Hi {username}, your OTP is {security_code}."

TwilioBackend#

class phone_verify.backends.twilio.TwilioBackend(**options)#

Twilio SMS backend implementation.

Required OPTIONS:

  • SID: Twilio Account SID

  • SECRET: Twilio Auth Token

  • FROM: Twilio phone number (E.164 format)

Example Configuration:

PHONE_VERIFICATION = {
    "BACKEND": "phone_verify.backends.twilio.TwilioBackend",
    "OPTIONS": {
        "SID": "ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "SECRET": "your_auth_token",
        "FROM": "+15551234567",
    },
    ...
}

NexmoBackend#

class phone_verify.backends.nexmo.NexmoBackend(**options)#

Nexmo (Vonage) SMS backend implementation.

Required OPTIONS:

  • KEY: Nexmo API Key

  • SECRET: Nexmo API Secret

  • FROM: Sender ID or phone number

Example Configuration:

PHONE_VERIFICATION = {
    "BACKEND": "phone_verify.backends.nexmo.NexmoBackend",
    "OPTIONS": {
        "KEY": "your_api_key",
        "SECRET": "your_api_secret",
        "FROM": "YourApp",
    },
    ...
}

Models#

SMSVerification#

class phone_verify.models.SMSVerification#

Database model for storing verification attempts.

Fields:

  • id (UUIDField): Primary key

  • phone_number (PhoneNumberField): Phone number being verified

  • security_code (CharField): The verification code sent

  • session_token (CharField): JWT token for this verification session

  • is_verified (BooleanField): Whether the code has been successfully verified

  • created_at (DateTimeField): When the verification was created

  • modified_at (DateTimeField): Last modification time

Constraints:

  • Unique together: (security_code, phone_number, session_token)

  • Ordered by: -modified_at (newest first)

Example Query:

from phone_verify.models import SMSVerification

# Find unverified codes for a phone number
pending = SMSVerification.objects.filter(
    phone_number="+1234567890",
    is_verified=False
)

Serializers#

PhoneSerializer#

class phone_verify.serializers.PhoneSerializer#

Simple serializer for phone number input.

Fields:

  • phone_number (PhoneNumberField): Required phone number field

Usage:

serializer = PhoneSerializer(data={"phone_number": "+1234567890"})
if serializer.is_valid():
    phone = serializer.validated_data["phone_number"]

SMSVerificationSerializer#

class phone_verify.serializers.SMSVerificationSerializer#

Serializer for verifying a security code.

Fields:

  • phone_number (PhoneNumberField): Phone number to verify

  • security_code (CharField): The code received via SMS

  • session_token (CharField): Session token from registration

Validation:

Automatically validates the security code against the backend and raises appropriate errors:

  • “Security code is not valid”

  • “Session Token mis-match”

  • “Security code has expired”

  • “Security code is already verified”

Usage:

serializer = SMSVerificationSerializer(data={
    "phone_number": "+1234567890",
    "security_code": "123456",
    "session_token": "eyJ0eXAi..."
})
serializer.is_valid(raise_exception=True)

ViewSets#

VerificationViewSet#

class phone_verify.api.VerificationViewSet#

DRF ViewSet with two main actions for phone verification flow.

Actions:

register(request)#

POST /api/phone/register

Send a security code to a phone number.

Request Body:

{
    "phone_number": "+1234567890"
}

Response:

{
    "session_token": "eyJ0eXAiOiJKV1QiLCJ..."
}
verify(request)#

POST /api/phone/verify

Verify a security code.

Request Body:

{
    "phone_number": "+1234567890",
    "security_code": "123456",
    "session_token": "eyJ0eXAiOiJKV1QiLCJ..."
}

Response:

{
    "message": "Security code is valid."
}

Extending:

You can extend this ViewSet to add custom actions:

from phone_verify.api import VerificationViewSet

class CustomVerificationViewSet(VerificationViewSet):
    @action(detail=False, methods=['POST'])
    def verify_and_login(self, request):
        # Custom logic here
        pass