Verify Currency Send SMS PIN
Verify the SMS PIN to authorize a currency send. This endpoint validates the PIN sent to the sender's phone and, upon success, automatically sends the claim code to the receiver via SMS.
/api/currency-sends/verify-sms
Verifies the SMS PIN and sends claim code to receiver
Authentication Required
Must include the same game secret key used to initiate the send:
X-Game-Secret-Key: your_game_secret_key_hereRequest Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| transaction_id | string | Yes | Transaction ID returned from initiate-send |
| 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 send 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 VerifySendSMSPin(string transactionId, string smsPin,
Action<string> onSuccess, Action<string> onError)
{
string url = "https://invo.network/api/currency-sends/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::VerifySendSMSPin(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/currency-sends/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::OnSendSMSVerified);
Request->ProcessRequest();
}GodotGodot GDScript SMS Verification
# This function MUST be called on your secure server.
func verify_send_sms_pin(transaction_id: String, sms_pin: String):
var url = "https://invo.network/api/currency-sends/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/currency-sends/verify-sms
Content-Type: application/json
X-Game-Secret-Key: your_game_secret_key_here
{
"transaction_id": "txn_send123abc456",
"sms_pin": "123456"
}Guardian-approval-aware responses
If the original send 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. A claim code has been sent to the receiver.",
"transaction_id": "txn_send123abc456",
"claim_code": "KJMRS-47281",
"claim_instructions": {
"message": "Claim code has been sent to the receiver via SMS.",
"receiving_game_id": "42",
"receiving_game_name": "Space Warriors",
"claim_code_expires_at": "2024-06-25T14:30:00Z",
"receiver_notified": true
},
"send_summary": {
"amount_sent": "500.00",
"net_amount_for_claim": "450.00",
"fees_deducted": "50.00",
"sender_current_available_balance": "750.00"
},
"order_id": "ord_send789def012"
}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 & Sent
A unique claim code is generated and automatically sent via SMS to the receiver's phone number provided during send initiation.
"You have received 450.00 Gold from PlayerOne. Claim code: KJMRS-47281. Use this in Space Warriors. Expires in 24 hours."
Send Status Updated
The send status changes from "pending_pin_verification" to "pending_claim". The funds remain reserved in the sender's account until the send is either claimed or expires.
24-Hour Claim Window
The receiver has 24 hours to claim the currency using the claim code. If not claimed within this time, the send expires and the net amount (minus fees) is automatically returned to the sender's balance.
Automatic Receiver Notification
How Receivers Are Notified
Unlike cross-game transfers where the sender manually shares the claim code, currency sends automatically notify the receiver via SMS. This creates a seamless experience for player-to-player transactions.
SMS Content Includes:
- • Amount and currency received
- • Sender's display name
- • Unique claim code
- • Target game name for claiming
- • 24-hour expiration notice
Note: The receiver doesn't need to have an account in the receiving game beforehand. If they don't exist as a player, a new account will be automatically created when they claim the currency.
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
- • 35 verification attempts per hour per player
- • 20 attempts per minute per transaction
- • 175 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 send state: Send 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 send 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 to receiver
- • 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 send if PIN expires
- • Show receiver notification status (SMS sent automatically)
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
- • Provide clear guidance when SMS delivery fails
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
- • Implement proper session management
Send Completion
- • Inform sender that receiver has been automatically notified
- • Display claim code for sender's reference (optional)
- • Show receiving game name and expiration time clearly
- • Update sender's balance to reflect reserved amount
- • Provide send tracking/history functionality