/api/client
Ricochet API
Validate licenses from your product, then use the private Developer API to manage products and customer access from trusted backend code.
POST /api/client
curl -X POST "https://dash.lucirift.com/api/client" \
-H "Authorization: YOUR_PUBLIC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"license":"USER_LICENSE_KEY","product":"MyProduct","version":"1.0.0"}'
Quick Start
https://dash.lucirift.com
PublicApiKey for client validation. SecretApiKey for backend-only admin routes.
Treat status_overview === "success" as the pass condition.
Auth Rules
Allowed only on POST /api/client. Safe for product-side validation calls.
Required for license and product management. Never ship this key inside client code.
/api/client
Validate License
Call this when your product starts. Ricochet checks the license, product match, expiry, IP cap, HWID cap, and blacklist state.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
license |
string | Required | Customer license key. |
product |
string | Required | Case-sensitive product name from the dashboard. |
version |
string | Required | Your product version string. |
ip |
string | Ignored | Ricochet derives the request IP from the server-side connection. |
hwid |
string | Optional | Hardware ID for HWID caps. |
Response Shape
{
"status_msg": "SUCCESSFUL_AUTHENTICATION",
"status_overview": "success",
"status_code": 200,
"status_id": "SUCCESS",
"version": "1.0.0",
"discord_username": "username",
"discord_tag": "username#0000",
"discord_id": "123456789012345678",
"expire_date": "Never"
}
Endpoint Reference
Grouped by the key each route expects. This keeps the page scannable without hiding the contract details.
PublicApiKey
SecretApiKey
/api/licenses
/api/licenses
/api/licenses/:license
/api/licenses/:license
/api/products
/api/products
/api/products/:name
/api/products/:name
Integration Examples
One focused client validation example per language. These are intentionally short so developers can copy the flow and adapt their own config handling.
import requests
data = requests.post(
"https://dash.lucirift.com/api/client",
headers={"Authorization": "YOUR_PUBLIC_API_KEY"},
json={"license": "USER_LICENSE_KEY", "product": "MyProduct", "version": "1.0.0"},
timeout=10
).json()
if data.get("status_overview") != "success":
raise SystemExit(data.get("status_msg", "LICENSE_FAILED"))
print("Authenticated:", data["discord_username"])
const res = await fetch("https://dash.lucirift.com/api/client", {
method: "POST",
headers: {
"Authorization": "YOUR_PUBLIC_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({
license: "USER_LICENSE_KEY",
product: "MyProduct",
version: "1.0.0"
})
});
const data = await res.json();
if (data.status_overview !== "success") throw new Error(data.status_msg);
console.log("Authenticated:", data.discord_username);
using System.Net.Http.Json;
using var http = new HttpClient();
http.DefaultRequestHeaders.Add("Authorization", "YOUR_PUBLIC_API_KEY");
var data = await http.PostAsJsonAsync("https://dash.lucirift.com/api/client", new {
license = "USER_LICENSE_KEY",
product = "MyProduct",
version = "1.0.0"
});
var body = await data.Content.ReadFromJsonAsync<Dictionary<string, object>>();
if ((string)body["status_overview"] != "success") throw new Exception((string)body["status_msg"]);
PerformHttpRequest("https://dash.lucirift.com/api/client", function(code, body)
local data = json.decode(body)
if data and data.status_overview == "success" then
print("[Auth] License valid: " .. data.discord_id)
else
print("[Auth] Failed: " .. ((data and data.status_msg) or "UNKNOWN"))
end
end, "POST", json.encode({
license = "USER_LICENSE_KEY",
product = "MyProduct",
version = "1.0.0"
}), {
["Authorization"] = "YOUR_PUBLIC_API_KEY",
["Content-Type"] = "application/json"
})
payload := strings.NewReader(`{"license":"USER_LICENSE_KEY","product":"MyProduct","version":"1.0.0"}`)
req, _ := http.NewRequest("POST", "https://dash.lucirift.com/api/client", payload)
req.Header.Set("Authorization", "YOUR_PUBLIC_API_KEY")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer res.Body.Close()
Status Messages
Failures return JSON with status_overview: "failed" and one of these status_msg values.
| Status | HTTP | Meaning |
|---|---|---|
SUCCESSFUL_AUTHENTICATION |
200 | License is valid. |
INVALID_REQUEST |
400 | Missing fields or wrong API key. |
INVALID_LICENSE |
400 | License key was not found. |
INVALID_PRODUCT |
400 | Product was not found. |
INVALID_LICENSE_FOR_PRODUCT |
400 | License belongs to another product. |
LICENSE_EXPIRED |
400 | License expiry date has passed. |
MAX_IP_CAP |
400 | Unique IP cap reached. |
MAX_HWID_CAP |
400 | Unique HWID cap reached. |
IP_BLACKLISTED |
403 | Client IP is blocked. |
HWID_BLACKLISTED |
403 | Client HWID is blocked. |
TOO_MANY_REQUESTS |
429 | Rate limit exceeded. |
status_overview first, then use status_msg to show a product-specific error.