Available Transfer Destinations API
Get the list of games that players can transfer currency to from your game. This endpoint should be called once daily and cached locally for optimal performance.
Performance Critical - Cache This Response!
✅ DO THIS
- • Call this API once per day
- • Cache response locally for 24 hours
- • Use cached data to build transfer UI
- • Refresh on app startup or manual refresh
❌ DON'T DO THIS
- • Call this API every time player opens transfer UI
- • Make requests during gameplay
- • Skip caching for "real-time" data
- • Store response only in memory
POST
/api/transfers/available-destinations
Get games that accept transfers from your game
Authentication Required
All requests must include your game's secret key in the request headers:
X-Game-Secret-Key: your_game_secret_key_hereRequest Body Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| source_game_id | string | Yes | Your game's ID (must match authenticated game) |
Transfer Logic Modes
Universal Transfers
universal_transfers = "yes"- • Returns: ALL live games that accept incoming transfers
- • Excludes: Your own game, testing games, inactive games
- • Best for: Maximum ecosystem connectivity
- • Configuration: Set in your game's database record
Linked Transfers
universal_transfers = "no"- • Returns: ONLY games in your
linked_game_idsfield - • Excludes: Testing games, inactive games
- • Best for: Curated partnerships, controlled ecosystem
- • Configuration: Manage linked_game_ids array in database
Request Example
POST /api/transfers/available-destinations
Content-Type: application/json
X-Game-Secret-Key: your_game_secret_key_here
{
"source_game_id": "123456789012"
}Response Examples
Universal Transfers - Success Response (200 OK)
{
"status": "success",
"source_game_id": "123456789012",
"source_game_name": "Adventure Quest",
"universal_transfers": "yes",
"transfer_mode": "universal",
"available_games": [
{
"game_id": "987654321098",
"game_name": "Space Warriors",
"developer_name": "Stellar Studios",
"publisher_name": "Galaxy Entertainment",
"genre": "Action",
"platform": "Mobile",
"game_status": "live",
"game_icon": "https://cdn.invo.network/games/space_icon.png",
"game_poster": "https://cdn.invo.network/games/space_poster.jpg",
"game_url": "https://spacewarriors.com",
"game_description": "Epic space combat game",
"currency_name": "Energy Credits",
"currency_symbol": "EC",
"currency_symbol_url": "https://cdn.invo.network/currencies/ec_icon.png",
"minimum_transfer": "5.00",
"maximum_transfer": "1000.00"
},
{
"game_id": "111222333444",
"game_name": "Fantasy Kingdom",
"developer_name": "Magic Studios",
"publisher_name": null,
"genre": "RPG",
"platform": "Web",
"game_status": "live",
"game_icon": "https://cdn.invo.network/games/fantasy_icon.png",
"game_poster": null,
"game_url": "https://fantasykingdom.com",
"game_description": "Build your magical empire",
"currency_name": "Gold Coins",
"currency_symbol": "GC",
"currency_symbol_url": null,
"minimum_transfer": "1.00",
"maximum_transfer": null
}
],
"total_destinations": 2
}Linked Transfers - Success Response (200 OK)
{
"status": "success",
"source_game_id": "123456789012",
"source_game_name": "Adventure Quest",
"universal_transfers": "no",
"transfer_mode": "linked",
"linked_game_ids": ["987654321098", "555666777888"],
"available_games": [
{
"game_id": "987654321098",
"game_name": "Space Warriors",
"developer_name": "Stellar Studios",
"publisher_name": "Galaxy Entertainment",
"genre": "Action",
"platform": "Mobile",
"game_status": "live",
"game_icon": "https://cdn.invo.network/games/space_icon.png",
"game_poster": "https://cdn.invo.network/games/space_poster.jpg",
"game_url": "https://spacewarriors.com",
"game_description": "Epic space combat game",
"currency_name": "Energy Credits",
"currency_symbol": "EC",
"currency_symbol_url": "https://cdn.invo.network/currencies/ec_icon.png",
"minimum_transfer": "5.00",
"maximum_transfer": "1000.00"
}
],
"total_destinations": 1
}No Destinations Available (200 OK)
{
"status": "success",
"source_game_id": "123456789012",
"source_game_name": "Adventure Quest",
"universal_transfers": "no",
"transfer_mode": "linked",
"linked_game_ids": [],
"available_games": [],
"total_destinations": 0,
"message": "No linked games configured for transfers"
}Error Response - Outgoing Transfers Disabled (403 Forbidden)
{
"status": "error",
"message": "Source game does not allow outgoing transfers"
}Implementation Examples
UnityUnity C# Available Destinations with Caching
// This function should be called once daily and cached
public IEnumerator GetAvailableDestinations(string sourceGameId, Action<string> onSuccess, Action<string> onError)
{
string url = "https://invo.network/api/transfers/available-destinations";
var requestData = new {
source_game_id = sourceGameId
};
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)
{
// Cache this response for 24 hours
CacheDestinationsResponse(request.downloadHandler.text);
onSuccess?.Invoke(request.downloadHandler.text);
}
else
{
onError?.Invoke(request.error + ": " + request.downloadHandler.text);
}
}
}
private void CacheDestinationsResponse(string jsonResponse)
{
PlayerPrefs.SetString("cached_destinations", jsonResponse);
PlayerPrefs.SetString("destinations_cache_time", System.DateTime.Now.ToBinary().ToString());
PlayerPrefs.Save();
Debug.Log("Destinations cached for 24 hours");
}
public string GetCachedDestinations()
{
if (!PlayerPrefs.HasKey("cached_destinations")) return null;
// Check if cache is expired (24 hours)
string cacheTimeStr = PlayerPrefs.GetString("destinations_cache_time");
if (!string.IsNullOrEmpty(cacheTimeStr))
{
long cacheTicks = System.Convert.ToInt64(cacheTimeStr);
System.DateTime cacheTime = System.DateTime.FromBinary(cacheTicks);
if ((System.DateTime.Now - cacheTime).TotalHours > 24)
{
// Cache expired
return null;
}
}
return PlayerPrefs.GetString("cached_destinations");
}UnrealUnreal C++ Available Destinations with Caching
// This function should be called once daily and cached
void AYourGameMode::GetAvailableDestinations(const FString& SourceGameId)
{
TSharedPtr<FJsonObject> RequestObj = MakeShareable(new FJsonObject);
RequestObj->SetStringField("source_game_id", SourceGameId);
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/available-destinations");
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::OnDestinationsReceived);
Request->ProcessRequest();
}
void AYourGameMode::OnDestinationsReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{
if (bWasSuccessful && Response.IsValid())
{
FString ResponseContent = Response->GetContentAsString();
if (Response->GetResponseCode() == 200)
{
// Cache the response for 24 hours
CacheDestinationsResponse(ResponseContent);
// Process the destinations data
ProcessDestinationsResponse(ResponseContent);
}
else
{
UE_LOG(LogTemp, Error, TEXT("Failed to get destinations: %s"), *ResponseContent);
}
}
else
{
UE_LOG(LogTemp, Error, TEXT("HTTP request failed"));
}
}
void AYourGameMode::CacheDestinationsResponse(const FString& JsonResponse)
{
// Save to game instance or persistent storage
if (UGameInstanceSubsystem* GameInstance = GetGameInstance()->GetSubsystem<UGameInstanceSubsystem>())
{
GameInstance->SetCachedDestinations(JsonResponse);
GameInstance->SetDestinationsCacheTime(FDateTime::Now());
UE_LOG(LogTemp, Log, TEXT("Destinations cached for 24 hours"));
}
}
FString AYourGameMode::GetCachedDestinations()
{
if (UGameInstanceSubsystem* GameInstance = GetGameInstance()->GetSubsystem<UGameInstanceSubsystem>())
{
FDateTime CacheTime = GameInstance->GetDestinationsCacheTime();
FDateTime Now = FDateTime::Now();
// Check if cache is expired (24 hours)
if ((Now - CacheTime).GetTotalHours() > 24.0)
{
return FString(); // Cache expired
}
return GameInstance->GetCachedDestinations();
}
return FString();
}GodotGodot GDScript Available Destinations with Caching
# This function should be called once daily and cached
func get_available_destinations(source_game_id: String):
var url = "https://invo.network/api/transfers/available-destinations"
var headers = [
"X-Game-Secret-Key: your_game_secret_key_here",
"Content-Type: application/json"
]
var body = {
"source_game_id": source_game_id
}
var http_request = HTTPRequest.new()
add_child(http_request)
http_request.request_completed.connect(_on_destinations_received)
http_request.request(url, headers, HTTPClient.METHOD_POST, JSON.stringify(body))
func _on_destinations_received(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray):
var json_string = body.get_string_from_utf8()
if response_code == 200:
# Cache the response for 24 hours
cache_destinations_response(json_string)
# Process the destinations data
process_destinations_response(json_string)
print("Destinations retrieved and cached successfully")
else:
print("Failed to get destinations: ", json_string)
func cache_destinations_response(json_response: String):
# Save to user data directory
var file = FileAccess.open("user://cached_destinations.json", FileAccess.WRITE)
if file:
var cache_data = {
"destinations": json_response,
"cache_time": Time.get_unix_time_from_system()
}
file.store_string(JSON.stringify(cache_data))
file.close()
print("Destinations cached for 24 hours")
func get_cached_destinations() -> String:
var file = FileAccess.open("user://cached_destinations.json", FileAccess.READ)
if not file:
return ""
var cache_data_str = file.get_as_text()
file.close()
var json = JSON.new()
var parse_result = json.parse(cache_data_str)
if parse_result != OK:
return ""
var cache_data = json.data
var cache_time = cache_data.get("cache_time", 0)
var current_time = Time.get_unix_time_from_system()
# Check if cache is expired (24 hours = 86400 seconds)
if (current_time - cache_time) > 86400:
print("Destinations cache expired")
return ""
return cache_data.get("destinations", "")
func should_refresh_destinations() -> bool:
var cached = get_cached_destinations()
return cached.is_empty()
# Call this on game startup
func initialize_destinations():
if should_refresh_destinations():
print("Refreshing destinations from API")
get_available_destinations("123456789012") # Your game ID
else:
print("Using cached destinations")
var cached_data = get_cached_destinations()
process_destinations_response(cached_data)
func process_destinations_response(json_response: String):
var json = JSON.new()
var parse_result = json.parse(json_response)
if parse_result != OK:
print("Error parsing destinations response")
return
var data = json.data
if data.get("status") == "success":
var available_games = data.get("available_games", [])
print("Available destinations: ", available_games.size())
# Build your transfer UI here using available_games data
else:
print("API error: ", data.get("message", "Unknown error"))Building Transfer UI from Response Data
Response Data Usage Guide
| Field | UI Usage | Example |
|---|---|---|
| game_name | Primary display text | "Space Warriors" |
| game_icon | Game thumbnail/logo | 64x64px icon next to name |
| currency_name | Currency description | "Energy Credits" |
| currency_symbol | Currency abbreviation | "EC" next to amounts |
| minimum_transfer | Input validation | Minimum value for amount field |
| maximum_transfer | Input validation | Maximum value (null = no limit) |
| developer_name | Secondary info | Small text under game name |
| genre | Filtering/categorization | Group games by type |
Sample Transfer UI Layout
Space Warriors
by Stellar Studios • Action
Energy Credits (EC)
Min: 5.00 • Max: 1,000.00
Fantasy Kingdom
by Magic Studios • RPG
Gold Coins (GC)
Min: 1.00 • No max
Error Handling
HTTP 400 - Bad Request
- • Missing source_game_id in request body
- • Invalid game ID format (not numeric)
- • Source game not found
HTTP 403 - Forbidden
- • Invalid or missing X-Game-Secret-Key header
- • Authenticated game doesn't match source_game_id
- • Source game has outgoing transfers disabled
HTTP 429 - Too Many Requests
- • IP address exceeded 100 requests per minute
- • Implement exponential backoff for retries
- • This shouldn't happen with proper daily caching
HTTP 500 - Server Error
- • Database connectivity issues
- • Internal system errors
- • Retry with exponential backoff
- • Fall back to cached data if available