🌹 Wild Rose Trucking — VTC API
Integrate your VTC website with Wild Rose Trucking. Authenticate users, pull stats, and display live data.
Overview
The Wild Rose VTC API allows external VTC websites to:
- Authenticate users via OAuth ("Login with Wild Rose")
- Fetch user profiles, avatars, and VTC membership
- Pull trucking stats (jobs, distance, revenue, XP)
- Access company/VTC information
Base URL: https://wild-rose-gaming.com
Getting Started
1. Create an OAuth Client
Go to your Manage VTC tab and scroll to the API / OAuth section. Fill in:
- App Name — Your VTC website name (shown to users during authorization)
- Redirect URI — The exact URL on your site that handles the callback (e.g.
https://yoursite.com/auth/callback)
You'll receive a client_id and client_secret. Store the secret securely — it's only shown once.
client_secret private. Never expose it in client-side JavaScript or public repositories.
OAuth Flow
Wild Rose uses a standard OAuth 2.0 Authorization Code flow:
Step 1: Redirect User to Authorize
Send the user to the Wild Rose authorization page:
GET https://wild-rose-gaming.com/oauth/authorize
?client_id=YOUR_CLIENT_ID
&redirect_uri=https://yoursite.com/auth/callback
&state=RANDOM_STRING
| Parameter | Required | Description |
|---|---|---|
| client_id | Yes | Your OAuth client ID |
| redirect_uri | Yes | Must exactly match the URI registered with your client |
| state | Recommended | Random string to prevent CSRF. Returned unchanged in the callback. |
The user will see a branded "Login with Wild Rose" page. If not logged in, they'll be prompted to sign in. They then approve or deny access.
Step 2: Handle the Callback
After approval, the user is redirected back to your redirect_uri with:
https://yoursite.com/auth/callback?code=AUTHORIZATION_CODE&state=YOUR_STATE
If denied:
https://yoursite.com/auth/callback?error=access_denied&state=YOUR_STATE
state matches what you sent. The authorization code expires in 5 minutes and can only be used once.
Step 3: Exchange Code for Access Token
Make a server-side POST request to exchange the code:
POST https://wild-rose-gaming.com/oauth/token
Content-Type: application/json
{
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"code": "AUTHORIZATION_CODE",
"redirect_uri": "https://yoursite.com/auth/callback"
}
Response:
{
"access_token": "abc123...",
"token_type": "Bearer",
"expires_in": 604800,
"user": {
"id": 1,
"username": "trucker_joe",
"display_name": "Trucker Joe",
"avatar": "https://wild-rose-gaming.com/uploads/staff/user_1_abc.jpg",
"company_id": 1,
"company_name": "Wild Rose Trucking",
"company_role": "driver"
}
}
Step 4: Use the Access Token
Include the token in subsequent API requests:
Authorization: Bearer YOUR_ACCESS_TOKEN
Tokens are valid for 7 days.
Authorization Endpoints
Authorization page — redirect users here to begin the OAuth flow.
| Parameter | Type | Description |
|---|---|---|
| client_id | string | Your OAuth client ID |
| redirect_uri | string | Callback URL (must match registered URI) |
| state | string | Anti-CSRF token (returned in callback) |
Exchange authorization code for an access token.
| Parameter | Type | Description |
|---|---|---|
| client_id | string | Your OAuth client ID |
| client_secret | string | Your OAuth client secret |
| code | string | Authorization code from callback |
| redirect_uri | string | Same redirect URI used in authorize request |
User Data Endpoints
Get the authenticated user's full profile, stats, recent jobs, and company driver leaderboard.
?access_token=TOKEN query parameter. The Authorization header gets stripped.
Response
{
"id": 1,
"username": "trucker_joe",
"display_name": "Trucker Joe",
"avatar": "https://wild-rose-gaming.com/uploads/staff/user_1_abc.jpg",
"email": "joe@example.com",
"company": {
"id": 1,
"name": "Wild Rose Trucking",
"tag": "WRT",
"color": "#FF6A2A",
"logo": "https://wild-rose-gaming.com/uploads/trucking/co_logo_1_abc.png",
"slug": "wild-rose-trucking"
},
"company_role": "driver",
"stats": {
"total_jobs": 142,
"total_distance": 85420,
"total_revenue": 4250000,
"total_xp": 28500
},
"recent_jobs": [
{
"cargo": "Electronics",
"source_city": "Las Vegas",
"source_company": "Tech Corp",
"destination_city": "Los Angeles",
"destination_company": "Retail Hub",
"distance": 420,
"planned_distance": 415,
"revenue": 32000,
"xp": 850,
"cargo_mass": 18500,
"cargo_damage": 0.001,
"truck_damage": 0.003,
"truck": "Kenworth W900",
"fuel_used": 145,
"duration": 1800,
"created_at": "2025-07-10 14:30:00"
}
],
"jobs_total": 142,
"jobs_page": 1,
"jobs_pages": 15,
"company_drivers": [
{
"id": 1,
"username": "trucker_joe",
"display_name": "Trucker Joe",
"avatar": "https://wild-rose-gaming.com/uploads/staff/user_1_abc.jpg",
"role": "driver",
"total_jobs": 142,
"total_distance": 85420,
"total_revenue": 4250000
}
],
"member_since": "2024-01-15 10:30:00"
}
| Parameter | Type | Description |
|---|---|---|
| access_token | string | OAuth access token (query param) |
| job_page | int | Page number for recent_jobs (optional, default 1, 10 per page) |
Get live driver positions for the authenticated user's company.
Response
{
"ok": true,
"drivers": [
{
"username": "trucker_joe",
"display_name": "Trucker Joe",
"avatar": "https://wild-rose-gaming.com/uploads/staff/user_1_abc.jpg",
"speed": 88.5,
"has_load": true,
"cargo": "Electronics",
"source_city": "Las Vegas",
"destination_city": "Los Angeles",
"game": "ats"
}
]
}
Get paginated delivery history for a specific driver in your company. Requires user token.
| Parameter | Type | Description |
|---|---|---|
| driver_id | int | The driver's user ID (from company_drivers array) |
| page | int | Page number (optional, default 1, 10 per page) |
| access_token | string | OAuth access token |
Response
{
"driver": { "id": 1, "name": "Trucker Joe" },
"jobs": [
{
"cargo": "Electronics",
"source_city": "Las Vegas",
"source_company": "Tech Corp",
"destination_city": "Los Angeles",
"destination_company": "Retail Hub",
"distance": 420,
"planned_distance": 415,
"revenue": 32000,
"xp": 850,
"cargo_mass": 18500,
"cargo_damage": 0.001,
"truck_damage": 0.003,
"truck": "Kenworth W900",
"fuel_used": 145,
"duration": 1800,
"created_at": "2025-07-10 14:30:00"
}
],
"total": 142,
"page": 1,
"pages": 15
}
Get paginated delivery history using client credentials. No user login needed — perfect for public driver profile pages.
| Parameter | Type | Description |
|---|---|---|
| client_id | string | Your OAuth client ID |
| client_secret | string | Your OAuth client secret |
| driver_id | int | The driver's user ID |
| page | int | Page number (optional, default 1, 10 per page) |
Response is identical to driver_jobs. Only returns drivers in your company.
client_secret in server-side code only.
Company Data Endpoints
Get public company stats using client credentials. No user token needed.
| Parameter | Type | Description |
|---|---|---|
| client_id | string | Your OAuth client ID |
| client_secret | string | Your OAuth client secret |
Response
{
"ok": true,
"company": {
"id": 1,
"name": "Wild Rose Trucking",
"tag": "WRT",
"color": "#FF6A2A",
"logo": "https://wild-rose-gaming.com/uploads/trucking/co_logo_1_abc.png",
"slug": "wild-rose-trucking"
},
"stats": {
"total_drivers": 12,
"total_jobs": 847,
"total_distance": 412000,
"total_revenue": 18200000,
"total_xp": 95000
},
"top_drivers": [
{
"id": 1,
"username": "trucker_joe",
"display_name": "Trucker Joe",
"avatar": "https://wild-rose-gaming.com/uploads/staff/user_1_abc.jpg",
"total_jobs": 142,
"total_distance": 85420,
"total_revenue": 4250000
}
]
}
Get live driver positions for your company.
{
"action": "get_positions",
"api_key": "YOUR_TRUCKING_API_KEY",
"company_id": 1
}
Response
{
"ok": true,
"drivers": [
{
"username": "trucker_joe",
"display_name": "Trucker Joe",
"avatar": "/uploads/staff/user_1_abc.jpg",
"pos_x": -95432.5,
"pos_y": 0,
"pos_z": 23456.7,
"heading": 1.57,
"speed": 88.5,
"has_load": true,
"cargo": "Electronics",
"source_city": "Las Vegas",
"destination_city": "Los Angeles",
"game": "ats",
"active": true
}
]
}
Company Management Endpoints
These endpoints require an OAuth token from a user with owner or manager role in their company. All use ?access_token=TOKEN for authentication.
owner or manager role. Application review also allows recruiter role.
Update company details. Requires owner or manager role.
| Parameter | Type | Description |
|---|---|---|
| name | string | Company name (required) |
| tag | string | Short tag (e.g. "WRT") |
| description | string | Company description |
| join_type | string | "open", "application", or "invite" |
| webhook | string | Discord webhook URL |
| color | string | Hex color (e.g. "#FF6A2A") |
| app_form | string | Application form slug |
Response
{ "ok": true }
Get available application forms that can be linked to your company. Requires owner or manager role.
Response
{
"ok": true,
"forms": [
{ "slug": "vtc-application", "name": "VTC Application Form" }
]
}
Change a company member's role. Requires owner or manager role. Only owners can promote to manager.
| Parameter | Type | Description |
|---|---|---|
| member_id | int | User ID of the member to update |
| role | string | "driver", "recruiter", or "manager" |
Response
{ "ok": true, "role": "manager" }
Get pending company applications. Requires owner, manager, or recruiter role.
Response
{
"ok": true,
"applications": [
{
"id": 12,
"username": "new_driver",
"display_name": "New Driver",
"avatar": "https://wild-rose-gaming.com/uploads/staff/user_5_abc.jpg",
"message": "I'd love to join your company!",
"created_at": "2025-07-10 09:00:00"
}
]
}
Approve a pending application. The user will be added to your company as a driver. Requires owner, manager, or recruiter role.
| Parameter | Type | Description |
|---|---|---|
| app_id | int | Application ID (from applications list) |
Response
{ "ok": true, "status": "approved" }
Decline a pending application. Requires owner, manager, or recruiter role.
| Parameter | Type | Description |
|---|---|---|
| app_id | int | Application ID (from applications list) |
Response
{ "ok": true, "status": "declined" }
Remove a member from your company. Requires owner or manager role. Cannot kick the owner.
| Parameter | Type | Description |
|---|---|---|
| member_id | int | User ID of the member to remove |
Response
{ "ok": true }
Error Responses (Management)
| Error | Cause |
|---|---|
| unauthorized | Missing or invalid access token |
| forbidden | User doesn't have required role (owner/manager/recruiter) |
| invalid_role | Role must be "driver", "recruiter", or "manager" |
| cannot_change_own | Cannot change your own role |
| cannot_change_owner | Cannot modify the company owner's role |
| cannot_kick_self | Cannot kick yourself |
| cannot_kick_owner | Cannot kick the company owner |
| member_not_found | Member ID not found in your company |
| not_found | Application or member not found |
| name_required | Company name is required for update_company |
Error Handling
All error responses follow this format:
{
"error": "error_code",
"message": "Human-readable description"
}
| Error Code | HTTP Status | Description |
|---|---|---|
| invalid_request | 400 | Missing or invalid parameters |
| invalid_client | 401 | Invalid client_id or client_secret |
| invalid_grant | 400 | Authorization code is invalid, expired, or already used |
| access_denied | — | User denied the authorization request |
| unauthorized | 401 | Missing or invalid access token |
| invalid_token | 401 | Access token has expired |
| server_error | 500 | Internal server error |
Cloudflare & Authorization Headers
Wild Rose Gaming sits behind Cloudflare. In some configurations, Cloudflare will strip the Authorization header from requests before they reach the origin server. This affects both server-side curl calls and client-side fetch requests.
{"error":"unauthorized","message":"Access token required"} despite sending a valid Bearer token, Cloudflare is likely stripping the header.
Solution: Use the Query Parameter
All endpoints that accept Authorization: Bearer TOKEN also accept the token as a query parameter:
GET /oauth/token?action=user&access_token=YOUR_TOKEN
This bypasses the header stripping entirely. Use this method when:
- Your site is on a different server/subdomain than
wild-rose-gaming.com - You're making client-side fetch requests from the browser
- Your server-side
curlcalls return "Access token required" despite sending the header
When Headers Work Fine
The Authorization header works without issues when:
- Calling from localhost / 127.0.0.1 on the same server (internal calls)
- The
POST /oauth/tokenendpoint (code exchange) — this usesContent-Type: application/jsonbody, not auth headers
Example: Client-Side Fetch
// ❌ May fail — Cloudflare strips the header
fetch('https://wild-rose-gaming.com/oauth/token?action=user', {
headers: { 'Authorization': 'Bearer ' + token }
});
// ✅ Always works — token in query string
fetch('https://wild-rose-gaming.com/oauth/token?action=user&access_token=' + token);
Example: Server-Side PHP
// ❌ May fail from external servers
$ch = curl_init('https://wild-rose-gaming.com/oauth/token?action=user');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $token]);
// ✅ Always works
$ch = curl_init('https://wild-rose-gaming.com/oauth/token?action=user&access_token=' . urlencode($token));
POST /oauth/token exchange (Step 3 of the OAuth flow) is unaffected — credentials go in the JSON body, not headers. Only GET requests with Bearer tokens are impacted.
Rate Limits
Please be respectful with API usage:
- User info endpoint: max 60 requests/minute per token
- Company stats: max 30 requests/minute per client
- Live drivers: max 12 requests/minute (poll every 5 seconds)
- Driver jobs: max 30 requests/minute per token
- Token exchange: max 10 requests/minute per client
Rate Limit Response
When you exceed the limit, you'll receive a 429 Too Many Requests response:
{
"error": "rate_limited",
"message": "Too many requests. Please wait before trying again.",
"retry_after": 30
}
| Field | Type | Description |
|---|---|---|
| retry_after | int | Seconds to wait before making another request |
company_stats with a 5-minute cache for public pages.
Try It
Test the API directly from this page. Paste your access token below to make live requests.
🔑 Token Tester
wild-rose-gaming.com. This runs entirely in your browser.
Full Example (PHP)
Here's a complete example of implementing "Login with Wild Rose" on your VTC site:
login.php — Redirect to Wild Rose
<?php
session_start();
$clientId = 'YOUR_CLIENT_ID';
$redirectUri = 'https://yoursite.com/auth/callback.php';
// Generate random state for CSRF protection
$state = bin2hex(random_bytes(16));
$_SESSION['oauth_state'] = $state;
// Redirect to Wild Rose
$url = 'https://wild-rose-gaming.com/oauth/authorize?' . http_build_query([
'client_id' => $clientId,
'redirect_uri' => $redirectUri,
'state' => $state,
]);
header('Location: ' . $url);
exit;
callback.php — Handle the response
<?php
session_start();
$clientId = 'YOUR_CLIENT_ID';
$clientSecret = 'YOUR_CLIENT_SECRET';
$redirectUri = 'https://yoursite.com/auth/callback.php';
// Verify state
if (($_GET['state'] ?? '') !== ($_SESSION['oauth_state'] ?? '')) {
die('Invalid state — possible CSRF attack');
}
unset($_SESSION['oauth_state']);
// Check for errors
if (isset($_GET['error'])) {
die('Authorization denied: ' . htmlspecialchars($_GET['error']));
}
// Exchange code for token
$code = $_GET['code'] ?? '';
$response = file_get_contents('https://wild-rose-gaming.com/oauth/token', false,
stream_context_create([
'http' => [
'method' => 'POST',
'header' => 'Content-Type: application/json',
'content' => json_encode([
'client_id' => $clientId,
'client_secret' => $clientSecret,
'code' => $code,
'redirect_uri' => $redirectUri,
]),
],
])
);
$data = json_decode($response, true);
if (!isset($data['access_token'])) {
die('Token exchange failed: ' . ($data['message'] ?? 'Unknown error'));
}
// Store in session
$_SESSION['access_token'] = $data['access_token'];
$_SESSION['user'] = $data['user'];
header('Location: /dashboard');
exit;
Fetching user data later
<?php
session_start();
$token = $_SESSION['access_token'] ?? '';
if (!$token) { header('Location: /login.php'); exit; }
// Use access_token query param (Cloudflare strips Authorization headers)
$response = file_get_contents(
'https://wild-rose-gaming.com/oauth/token?action=user&access_token=' . urlencode($token)
);
$user = json_decode($response, true);
echo 'Welcome, ' . htmlspecialchars($user['display_name']);
echo '<br>Total distance: ' . number_format($user['stats']['total_distance']) . ' km';
echo '<br>Company: ' . htmlspecialchars($user['company']['name'] ?? 'None');
Fetching company stats (no user login needed)
<?php
// Public company stats using client credentials
$response = file_get_contents(
'https://wild-rose-gaming.com/oauth/token?action=company_stats'
. '&client_id=' . urlencode($clientId)
. '&client_secret=' . urlencode($clientSecret)
);
$data = json_decode($response, true);
if ($data['ok']) {
echo $data['company']['name'] . ' — ' . $data['stats']['total_drivers'] . ' drivers';
echo '<br>' . number_format($data['stats']['total_jobs']) . ' deliveries';
echo '<br>' . number_format($data['stats']['total_distance']) . ' km driven';
}
Changelog
📝 Version History
action=company_stats — public stats via client credentials• Added
action=live_drivers — live positions via OAuth• Added
action=driver_jobs — paginated delivery history• Added company management endpoints (update_company, update_role, applications, kick_member)
• Documented Cloudflare header stripping — use
?access_token= query param• Added
/docs/api.txt machine-readable endpoint•
action=user now returns company_drivers, recent_jobs, and pagination
company_drivers array to user endpoint• Added
recent_jobs with full delivery details• Token response now includes user object
• OAuth 2.0 Authorization Code flow
• User profile + stats endpoint
• Trucking API positions endpoint
Machine-Readable Docs (for AI / curl)
Need a quick summary an LLM or script can parse? Hit the plaintext endpoint:
Returns a plain-text summary of the entire API — perfect for piping into an AI assistant or quick reference via curl.
curl https://api.wild-rose-gaming.com/api.txt
curl -s https://api.wild-rose-gaming.com/api.txt | llm "write me a PHP integration"
Live Map Embed
Embed the Wild Rose live map directly on your VTC site using an iframe. Authenticates with your client_id — no user token needed.
Embeddable live map showing your company's drivers in real-time.
Usage
<iframe
src="https://wild-rose-gaming.com/livemap?embed&client_id=YOUR_CLIENT_ID"
style="width:100%;height:600px;border:none;border-radius:12px;"
allow="fullscreen"
></iframe>
client_id.
Full-Page Example
<!-- Full-height map page -->
<div style="position:fixed;inset:0;">
<iframe
src="https://wild-rose-gaming.com/livemap?embed&client_id=YOUR_CLIENT_ID"
style="width:100%;height:100%;border:none;"
allow="fullscreen"
></iframe>
</div>
Support
Having issues with the API? Reach out on our Discord server.