Verify SMS PIN
Verify the SMS PIN to authorize a transfer. This endpoint validates the PIN sent to the player's phone and, upon success, generates a claim code that can be shared with the intended recipient.
/api/transfers/verify-sms
Verifies the SMS PIN and authorizes the transfer
Authentication Required
Must include the same game secret key used to initiate the transfer:
X-Game-Secret-Key: your_game_secret_key_hereRequest Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| transaction_id | string | Yes | Transaction ID returned from initiate-transfer |
| sms_pin | string | Yes | 6-digit PIN received via SMS |
SMS PIN Requirements
PIN Format
- • 6-digit numeric code
- • Case-sensitive (numbers only)
- • Unique per transfer attempt
- • One-time use only
Time Limits
- • PIN expires in 10 minutes
- • Maximum 3 verification attempts
- • Failed attempts count toward rate limits
- • Expired PINs cannot be reused
Implementation Examples
UnityUnity C# SMS Verification
// This function MUST be called on your secure server, NOT the client.
public IEnumerator VerifySMSPin(string transactionId, string smsPin,
Action<string> onSuccess, Action<string> onError)
{
string url = "https://invo.network/api/transfers/verify-sms";
var requestData = new {
transaction_id = transactionId,
sms_pin = smsPin
};
string jsonBody = JsonUtility.ToJson(requestData);
using (UnityWebRequest request = new UnityWebRequest(url, "POST"))
{
byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonBody);
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("X-Game-Secret-Key", "your_game_secret_key_here");
request.SetRequestHeader("Content-Type", "application/json");
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
onSuccess?.Invoke(request.downloadHandler.text);
}
else
{
onError?.Invoke(request.error + ": " + request.downloadHandler.text);
}
}
}UnrealUnreal C++ SMS Verification
// This function MUST be called on your secure server.
void AYourGameMode::VerifySMSPin(const FString& TransactionId, const FString& SMSPin)
{
TSharedPtr<FJsonObject> RequestObj = MakeShareable(new FJsonObject);
RequestObj->SetStringField("transaction_id", TransactionId);
RequestObj->SetStringField("sms_pin", SMSPin);
FString RequestBody;
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&RequestBody);
FJsonSerializer::Serialize(RequestObj.ToSharedRef(), Writer);
TSharedRef<IHttpRequest> Request = FHttpModule::Get().CreateRequest();
Request->SetURL("https://invo.network/api/transfers/verify-sms");
Request->SetVerb("POST");
Request->SetHeader("X-Game-Secret-Key", "your_game_secret_key_here");
Request->SetHeader("Content-Type", "application/json");
Request->SetContentAsString(RequestBody);
Request->OnProcessRequestComplete().BindUObject(this, &AYourGameMode::OnSMSVerified);
Request->ProcessRequest();
}GodotGodot GDScript SMS Verification
# This function MUST be called on your secure server.
func verify_sms_pin(transaction_id: String, sms_pin: String):
var url = "https://invo.network/api/transfers/verify-sms"
var headers = [
"X-Game-Secret-Key: your_game_secret_key_here",
"Content-Type: application/json"
]
var body = {
"transaction_id": transaction_id,
"sms_pin": sms_pin
}
http_request.request(url, headers, HTTPClient.METHOD_POST, JSON.stringify(body))
Request & Response Examples
Example Request
POST /api/transfers/verify-sms
Content-Type: application/json
X-Game-Secret-Key: your_game_secret_key_here
{
"transaction_id": "txn_abc123def456",
"sms_pin": "123456"
}Guardian-approval-aware responses
If the original transaction was initiated by a minor account, this endpoint may return:
- 202
GUARDIAN_APPROVAL_PENDING— guardian hasn't replied yet. The same call succeeds normally once approval lands; just keep polling. - 410
GUARDIAN_APPROVAL_REJECTEDorGUARDIAN_APPROVAL_EXPIRED— terminal. Show a clear message; user must re-initiate.
Full state machine: Guardian Approval.
Success Response (200 OK)
{
"status": "success",
"message": "SMS verification successful. Transfer is now pending claim by receiver.",
"transaction_id": "txn_abc123def456",
"claim_code": "KJMRS-47281",
"claim_instructions": {
"message": "Provide this claim code to the intended receiver.",
"target_game_id": "42",
"target_game_name": "Space Warriors",
"claim_code_expires_at": "2024-06-25T14:30:00Z"
},
"transfer_summary": {
"amount_initiated": "500.00",
"net_amount_for_claim": "450.00",
"fees_deducted": "50.00",
"source_player_current_available_balance": "750.00"
},
"order_id": "TFRO_1719235200_A1B2C3D4"
}Error Response - Invalid PIN (400 Bad Request)
{
"status": "error",
"message": "Invalid SMS PIN.",
"attempts_remaining": 2
}Error Response - Expired PIN (400 Bad Request)
{
"status": "error",
"message": "SMS PIN is not valid: PIN expired."
}Error Response - Rate Limited (429 Too Many Requests)
{
"error": "sms_verification_blocked",
"message": "Too many SMS verification attempts. Please try again in 1 hour.",
"retry_after": 3600
}What Happens After Successful Verification
Claim Code Generated
A unique claim code is generated and included in the response. This code is also sent via SMS to the sender for easy sharing.
"Your Invo transfer to Space Warriors claim code is KJMRS-47281. Valid for 24 hours. Our employees will never ask you for this code."
Transfer Status Updated
The transfer status changes from "pending_pin_verification" to "pending_claim". The funds remain reserved in the sender's account until the transfer is either claimed or expires.
24-Hour Claim Window
The recipient has 24 hours to claim the transfer using the claim code. If not claimed within this time, the transfer expires and the net amount (minus fees) is automatically returned to the sender's balance.
Security Features
PIN Protection
- • Hashed storage - PINs never stored in plain text
- • Limited attempts - Maximum 3 verification tries
- • Time-based expiry - 10 minute validity window
- • One-time use - PIN becomes invalid after successful verification
Rate Limiting
- • 40 verification attempts per hour per player
- • 20 attempts per minute per transaction
- • 200 attempts per hour per IP address
- • Failed attempts trigger progressive blocking
Fraud Detection
- • SMS verification spam detection
- • Invalid PIN attempt tracking
- • IP-based suspicious activity monitoring
- • Automatic blocking for repeated failures
Transaction Integrity
- • Funds remain reserved during verification
- • Automatic cleanup of expired transactions
- • Comprehensive audit trail
- • Circuit breaker for service protection
Common Error Scenarios
HTTP 400 - Bad Request
- • Invalid SMS PIN: PIN doesn't match or has wrong format
- • PIN expired: More than 10 minutes have passed since initiation
- • Max attempts reached: 3 incorrect PIN attempts used up
- • Missing parameters: transaction_id or sms_pin not provided
- • Wrong transfer state: Transfer not in pending_pin_verification status
HTTP 404 - Not Found
- • Transaction not found: Invalid transaction_id or wrong game
- • Unauthorized access: Game secret key doesn't match transfer source
HTTP 429 - Too Many Requests
- • SMS verification spam: Too many verification attempts from player
- • Transaction rate limit: Too many attempts for specific transaction
- • IP rate limit: Too many requests from the same network
- • Invalid PIN blocking: Player blocked due to repeated invalid PINs
HTTP 500 - Server Error
- • Database connectivity: Temporary database issues
- • SMS service error: Unable to send claim code SMS
- • Circuit breaker open: Service temporarily unavailable
Implementation Best Practices
User Experience
- • Display remaining attempts when PIN verification fails
- • Show countdown timer for PIN expiration
- • Provide clear error messages for different failure scenarios
- • Allow users to request a new transfer if PIN expires
Error Handling
- • Parse error responses to show appropriate user messages
- • Handle rate limiting with retry logic and user feedback
- • Implement exponential backoff for server errors
- • Log all API responses for debugging and monitoring
Security
- • Never log or store SMS PINs in your application
- • Validate PIN format on client side before sending
- • Clear PIN input fields after submission
- • Use HTTPS for all API communications
Claim Code Sharing
- • Display claim code prominently after successful verification
- • Provide easy copy-to-clipboard functionality
- • Show target game name and expiration time clearly
- • Consider QR code generation for mobile sharing