Console
Guide

Friends

Friends, presence, chat, notifications, and game invites — integrated into Vanelton ID so users can connect across all your apps.

Endpoints overview

EndpointAction
POST /api/vaneltonid/friend_request.phpSend a friend request
POST /api/vaneltonid/friend_accept.phpAccept a pending request
POST /api/vaneltonid/friend_remove.phpRemove a friend or cancel a request
POST /api/vaneltonid/friend_list.phpList confirmed friends
POST /api/vaneltonid/friend_pending.phpList incoming pending requests
POST /api/vaneltonid/friend_sent.phpList outgoing pending requests
POST /api/vaneltonid/friend_search.phpSearch users by username prefix
POST /api/vaneltonid/user_profile.phpGet a user's public profile
POST /api/vaneltonid/friend_block.phpBlock or unblock a user
POST /api/vaneltonid/presence_heartbeat.phpUpdate presence + get friends' status (every 30s)
POST /api/vaneltonid/notifications_poll.phpFetch unread notifications (every 5–10s)
POST /api/vaneltonid/notifications_read.phpMark notifications as read
POST /api/vaneltonid/game_invite.phpSend or respond to a game invite
POST /api/vaneltonid/chat_send.phpSend a chat message
POST /api/vaneltonid/chat_history.phpLoad conversation history
POST /api/vaneltonid/chat_poll.phpFetch new messages since a timestamp (every 5s)

All endpoints require Authorization: AppID:AppKey header + token in the request body.

Friend flow

User A sends request → friend_request  (token A, receiver_userkey = B)
User B sees pending  → friend_pending  (token B)
User B accepts       → friend_accept   (token B, sender_userkey = A)
Both appear in each other's friend_list

Launcher polling loop

For presence and real-time notifications, the launcher should run three polling loops:

Every 30s:
  └─ POST /presence_heartbeat → friends' presence + unread_notifications count

Every 5s:
  ├─ POST /chat_poll (since: last server_time) → new messages from any friend
  └─ (if unread_notifications > 0) POST /notifications_poll → friend requests, game invites

On app open:
  └─ POST /chat_history (friend_id: ...) → load full history; save server_time as `since`

When entering a game:
  └─ POST /presence_heartbeat (status: "in-game", current_app: "com.app")

1. Send a friend request

You need the target user's userkey — obtained from their profile or from the login response.

await fetch('https://vaneltonmedia.com/api/vaneltonid/friend_request.php', {
  method: 'POST',
  headers: {
    'Authorization': `${APP_ID}:${APP_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    token:             localStorage.getItem('vm_token'),
    receiver_userkey:  'abc123userkey'
  })
});
const apiPost = (path: string, body: object) =>
  fetch(`https://vaneltonmedia.com${path}`, {
    method: 'POST',
    headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ token: localStorage.getItem('vm_token'), ...body })
  }).then(r => r.json());

await apiPost('/api/vaneltonid/friend_request.php', { receiver_userkey: 'abc123userkey' });
function friendRequest(string $receiverUserkey): array {
    $ch = curl_init('https://vaneltonmedia.com/api/vaneltonid/friend_request.php');
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_HTTPHEADER => ['Authorization: ' . APP_ID . ':' . APP_KEY, 'Content-Type: application/json'],
        CURLOPT_POSTFIELDS => json_encode([
            'token' => $_SESSION['vm_token'],
            'receiver_userkey' => $receiverUserkey,
        ]),
    ]);
    $result = json_decode(curl_exec($ch), true);
    curl_close($ch);
    return $result;
}
import requests

HEADERS = {'Authorization': f'{APP_ID}:{APP_KEY}', 'Content-Type': 'application/json'}

def friend_api(endpoint, token, **kwargs):
    return requests.post(
        f'https://vaneltonmedia.com/api/vaneltonid/{endpoint}',
        headers=HEADERS,
        json={'token': token, **kwargs}
    ).json()

friend_api('friend_request.php', token, receiver_userkey='abc123userkey')
var _headers = ds_map_create();
ds_map_add(_headers, "Authorization", global.app_id + ":" + global.app_key);
ds_map_add(_headers, "Content-Type",  "application/json");

http_request(
    "https://vaneltonmedia.com/api/vaneltonid/friend_request.php",
    "POST", _headers,
    json_stringify({ token: global.user_token, receiver_userkey: "abc123userkey" })
);
ds_map_destroy(_headers);
APP_ID="com.myapp.game"
APP_KEY="MyAppKey1234567890ABCDE"
TOKEN="YOUR_SESSION_TOKEN"

curl -s -X POST "https://vaneltonmedia.com/api/vaneltonid/friend_request.php" \
  -H "Authorization: $APP_ID:$APP_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"token\":\"$TOKEN\",\"receiver_userkey\":\"abc123userkey\"}"
using System.Net.Http;
using System.Text;
using System.Text.Json;

const string APP_ID  = "com.myapp.game";
const string APP_KEY = "MyAppKey1234567890ABCDE";

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"{APP_ID}:{APP_KEY}");

async Task FriendPost(string endpoint, object body)
{
    var payload = JsonSerializer.Serialize(body);
    await client.PostAsync(
        $"https://vaneltonmedia.com/api/vaneltonid/{endpoint}",
        new StringContent(payload, Encoding.UTF8, "application/json"));
}

await FriendPost("friend_request.php", new { token, receiver_userkey = "abc123userkey" });
-- Requires: luarocks install luasocket luasec lua-cjson
local http  = require("socket.http")
local ltn12 = require("ltn12")
local json  = require("cjson")

local APP_ID  = "com.myapp.game"
local APP_KEY = "MyAppKey1234567890ABCDE"

local function friend_api(endpoint, body_tbl)
    local body   = json.encode(body_tbl)
    local chunks = {}
    http.request {
        url    = "https://vaneltonmedia.com/api/vaneltonid/" .. endpoint,
        method = "POST",
        headers = {
            ["Authorization"]  = APP_ID .. ":" .. APP_KEY,
            ["Content-Type"]   = "application/json",
            ["Content-Length"] = #body,
        },
        source = ltn12.source.string(body),
        sink   = ltn12.sink.table(chunks),
    }
    return json.decode(table.concat(chunks))
end

friend_api("friend_request.php", { token = token, receiver_userkey = "abc123userkey" })

2. Check incoming requests

const res = await fetch('https://vaneltonmedia.com/api/vaneltonid/friend_pending.php', {
  method: 'POST',
  headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: localStorage.getItem('vm_token') })
});
const { pending, count } = await res.json();
// pending = [{ id, userkey, username, name, profileimg }, ...]
const res = await fetch('https://vaneltonmedia.com/api/vaneltonid/friend_pending.php', {
  method: 'POST',
  headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: localStorage.getItem('vm_token') })
});
const { pending, count } = await res.json();
$ch = curl_init('https://vaneltonmedia.com/api/vaneltonid/friend_pending.php');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: ' . APP_ID . ':' . APP_KEY, 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode(['token' => $_SESSION['vm_token']]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);

foreach ($result['pending'] as $req) {
    echo $req['name'] . ' (' . $req['username'] . ')' . PHP_EOL;
}
result = friend_api('friend_pending.php', token)
print(f"{result['count']} pending request(s):")
for req in result['pending']:
    print(f"  - {req['name']} ({req['username']})")
var _headers = ds_map_create();
ds_map_add(_headers, "Authorization", global.app_id + ":" + global.app_key);
ds_map_add(_headers, "Content-Type",  "application/json");

global.pending_req = http_request(
    "https://vaneltonmedia.com/api/vaneltonid/friend_pending.php",
    "POST", _headers,
    json_stringify({ token: global.user_token })
);
ds_map_destroy(_headers);

// --- In Async HTTP Event ---
if (async_load[? "id"] == global.pending_req) {
    var _d = json_parse(async_load[? "result"]);
    show_debug_message("Pending: " + string(_d.count));
}
curl -s -X POST "https://vaneltonmedia.com/api/vaneltonid/friend_pending.php" \
  -H "Authorization: $APP_ID:$APP_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"token\":\"$TOKEN\"}"
var payload = JsonSerializer.Serialize(new { token });
using var res = await client.PostAsync(
    "https://vaneltonmedia.com/api/vaneltonid/friend_pending.php",
    new StringContent(payload, Encoding.UTF8, "application/json"));

using var doc = JsonDocument.Parse(await res.Content.ReadAsStringAsync());
var pending = doc.RootElement.GetProperty("pending");
int count   = doc.RootElement.GetProperty("count").GetInt32();
local result = friend_api("friend_pending.php", { token = token })
print(result.count .. " pending request(s)")
for _, req in ipairs(result.pending) do
    print("  - " .. req.name .. " (" .. req.username .. ")")
end

3. Accept a request

await fetch('https://vaneltonmedia.com/api/vaneltonid/friend_accept.php', {
  method: 'POST',
  headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({
    token:          localStorage.getItem('vm_token'),
    sender_userkey: pending[0].userkey
  })
});
await apiPost('/api/vaneltonid/friend_accept.php', { sender_userkey: pending[0].userkey });
$ch = curl_init('https://vaneltonmedia.com/api/vaneltonid/friend_accept.php');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: ' . APP_ID . ':' . APP_KEY, 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode([
        'token' => $_SESSION['vm_token'],
        'sender_userkey' => $pending[0]['userkey'],
    ]),
]);
curl_exec($ch); curl_close($ch);
friend_api('friend_accept.php', token, sender_userkey=pending[0]['userkey'])
var _headers = ds_map_create();
ds_map_add(_headers, "Authorization", global.app_id + ":" + global.app_key);
ds_map_add(_headers, "Content-Type",  "application/json");

http_request(
    "https://vaneltonmedia.com/api/vaneltonid/friend_accept.php",
    "POST", _headers,
    json_stringify({ token: global.user_token, sender_userkey: "abc123userkey" })
);
ds_map_destroy(_headers);
curl -s -X POST "https://vaneltonmedia.com/api/vaneltonid/friend_accept.php" \
  -H "Authorization: $APP_ID:$APP_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"token\":\"$TOKEN\",\"sender_userkey\":\"abc123userkey\"}"
await FriendPost("friend_accept.php", new { token, sender_userkey = senderUserkey });
friend_api("friend_accept.php", { token = token, sender_userkey = "abc123userkey" })

4. List friends

const res = await fetch('https://vaneltonmedia.com/api/vaneltonid/friend_list.php', {
  method: 'POST',
  headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: localStorage.getItem('vm_token') })
});
const { friends, count } = await res.json();
console.log(`You have ${count} friend(s).`);
const { friends, count } = await apiPost('/api/vaneltonid/friend_list.php', {});
console.log(`You have ${count} friend(s).`);
$ch = curl_init('https://vaneltonmedia.com/api/vaneltonid/friend_list.php');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: ' . APP_ID . ':' . APP_KEY, 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode(['token' => $_SESSION['vm_token']]),
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);

echo "You have " . $result['count'] . " friend(s).";
result = friend_api('friend_list.php', token)
print(f"You have {result['count']} friend(s).")
for f in result['friends']:
    print(f"  - {f['name']} ({f['username']})")
var _headers = ds_map_create();
ds_map_add(_headers, "Authorization", global.app_id + ":" + global.app_key);
ds_map_add(_headers, "Content-Type",  "application/json");

global.friends_req = http_request(
    "https://vaneltonmedia.com/api/vaneltonid/friend_list.php",
    "POST", _headers,
    json_stringify({ token: global.user_token })
);
ds_map_destroy(_headers);

// --- In Async HTTP Event ---
if (async_load[? "id"] == global.friends_req) {
    var _d = json_parse(async_load[? "result"]);
    show_debug_message("Friends: " + string(_d.count));
    // _d.friends is an array of friend objects
}
curl -s -X POST "https://vaneltonmedia.com/api/vaneltonid/friend_list.php" \
  -H "Authorization: $APP_ID:$APP_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"token\":\"$TOKEN\"}"
var payload = JsonSerializer.Serialize(new { token });
using var res = await client.PostAsync(
    "https://vaneltonmedia.com/api/vaneltonid/friend_list.php",
    new StringContent(payload, Encoding.UTF8, "application/json"));

using var doc = JsonDocument.Parse(await res.Content.ReadAsStringAsync());
int count   = doc.RootElement.GetProperty("count").GetInt32();
Console.WriteLine($"You have {count} friend(s).");
local result = friend_api("friend_list.php", { token = token })
print("You have " .. result.count .. " friend(s).")
for _, f in ipairs(result.friends) do
    print("  - " .. f.name .. " (" .. f.username .. ")")
end

5. Remove a friend

await fetch('https://vaneltonmedia.com/api/vaneltonid/friend_remove.php', {
  method: 'POST',
  headers: { 'Authorization': `${APP_ID}:${APP_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ token: localStorage.getItem('vm_token'), target_userkey: 'abc123userkey' })
});
await apiPost('/api/vaneltonid/friend_remove.php', { target_userkey: 'abc123userkey' });
$ch = curl_init('https://vaneltonmedia.com/api/vaneltonid/friend_remove.php');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: ' . APP_ID . ':' . APP_KEY, 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode(['token' => $_SESSION['vm_token'], 'target_userkey' => 'abc123userkey']),
]);
curl_exec($ch); curl_close($ch);
friend_api('friend_remove.php', token, target_userkey='abc123userkey')
var _headers = ds_map_create();
ds_map_add(_headers, "Authorization", global.app_id + ":" + global.app_key);
ds_map_add(_headers, "Content-Type",  "application/json");

http_request(
    "https://vaneltonmedia.com/api/vaneltonid/friend_remove.php",
    "POST", _headers,
    json_stringify({ token: global.user_token, target_userkey: "abc123userkey" })
);
ds_map_destroy(_headers);
curl -s -X POST "https://vaneltonmedia.com/api/vaneltonid/friend_remove.php" \
  -H "Authorization: $APP_ID:$APP_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"token\":\"$TOKEN\",\"target_userkey\":\"abc123userkey\"}"
await FriendPost("friend_remove.php", new { token, target_userkey = "abc123userkey" });
friend_api("friend_remove.php", { token = token, target_userkey = "abc123userkey" })