Integration guide
For developers building on the ByteMaple license system: accounts, license keys, ad-free behaviour and push notifications.
The flow, in one paragraph
The user buys a package on this website (signing in with Google, paying with PayPal). The site issues a license key such as BM-K7QX2M-9FRT4A-ZP8W3D. Inside your app or program the user pastes that key; your code calls the activate endpoint once, then the verify endpoint on every start and once a day. While verify answers ad_free: true the app removes its ads; the moment it answers false (expired, revoked or over the device limit) the app shows ads again. The same package system covers three product types — games, apps and software — and a package can cover one or several of them, either every product of those types or a picked list.
1. Accounts: Google sign-in
Accounts live on this website only — apps never ask for a Google password. Send the user to https://bytemaple.com/login in a browser (or an in-app browser tab) to sign in, buy a package, and copy their key from https://bytemaple.com/account. Your app only ever handles the license key.
2. Entering a license key
Add a “Remove ads / I have a license key” screen in your settings. Ask for the key (accept any case, trim spaces), store it in your app's private storage, and call activate.
3. API: activate
POST https://bytemaple.com/api/license/activate — binds the key to this device for this app. Activations are counted per app: a key works on at most 3 devices in each app it covers, so the user's other apps never use up this app's slots. devices_used in the answers counts this app's activations only.
Request:
{
"key": "BM-K7QX2M-9FRT4A-ZP8W3D",
"app": "com.ludostrike.game",
"device_id": "a1b2c3-install-uuid",
"device_name": "DESKTOP-AB12CD",
"platform": "android"
}
app is your product's package name (Windows: its slug works too). device_id is a stable id your app generates once per install and keeps. device_name is optional — a human-readable name for the device or computer (e.g. the Windows computer name); when sent it is stored on the activation and shown in the admin. Clients that omit it keep working unchanged. platform is android or windows.
Success — 200:
{
"valid": true,
"ad_free": true,
"expires_at": "2027-01-26T10:00:00+00:00",
"package_name": "com.ludostrike.game",
"plan": "Ad-Free Monthly",
"devices_used": 1,
"devices_max": 3
}
Failure — 404/403 with { valid: false, ad_free: false, error, message }. Error codes: unknown_app, unknown_key, revoked, expired, not_covered (the package doesn't include this product), device_limit.
4. API: verify
POST https://bytemaple.com/api/license/verify with { key, app, device_id } (the optional device_name is accepted here too and refreshes the stored name). Always answers 200:
{
"valid": true,
"ad_free": true,
"expires_at": "2027-01-26T10:00:00+00:00",
"package_name": "com.ludostrike.game",
"plan": "Ad-Free Monthly",
"devices_used": 1,
"devices_max": 3
}
- When to call: on app start, then at least once a day while the app is used. Cache the last good answer for offline starts, but never for more than 24 hours.
ad_free: true→ remove ads (next section).false→ show ads again immediately. This is how an expired or refunded license returns ads on its own.expires_atisnullfor lifetime keys.
5. API: deactivate
POST https://bytemaple.com/api/license/deactivate with { key, app, device_id } — releases this device's slot for this app, so the user can activate the app on another device. Answers 200 with { ok: true, deactivated: true }, or deactivated: false when this device had no activation for this app. Unknown apps/keys answer the same 404 shapes as activate. Users can also release any activation themselves from their account page on this website.
6. Ad-free behaviour in the app
- Do not just hide the ad view — remove it from the layout (Android:
View.GONE, neverINVISIBLE; WPF/WinForms:Visibility.Collapsed). The empty ad slot must close up so the rest of the screen stretches and fits — no blank band where the banner was. - Stop requesting ads entirely while ad-free (no ad SDK calls in the background).
- Rewarded options that ads unlock should stay reachable — grant them directly or leave a free button; never punish a paying user.
- When verify flips back to
ad_free: false, rebuild the ad container and resume normal ad loading.
Kotlin (Android) sketch
val body = JSONObject()
.put("key", storedKey)
.put("app", context.packageName)
.put("device_id", installId)
.put("platform", "android")
val res = postJson("https://bytemaple.com/api/license/verify", body)
if (res.optBoolean("ad_free")) {
adContainer.removeAllViews()
adContainer.visibility = View.GONE // space collapses, layout refits
adsEnabled = false
} else {
adsEnabled = true // build the banner and load ads again
}
C# (Windows) sketch
var payload = new { key = storedKey, app = "ludo-strike", device_id = installId };
var res = await http.PostAsJsonAsync("https://bytemaple.com/api/license/verify", payload);
var state = await res.Content.ReadFromJsonAsync<VerifyState>();
AdBanner.Visibility = state.AdFree ? Visibility.Collapsed // not Hidden
: Visibility.Visible;
7. Push notifications
Register every install once (and whenever the push token changes):
POST https://bytemaple.com/api/devices/register
{
"platform": "android",
"app": "com.ludostrike.game",
"install_id": "a1b2c3-install-uuid",
"push_token": "fcm-token\u2026",
"country": "IN"
}
- Android: send the FCM token as
push_token. Notifications arrive through Firebase with the campaign's title/body/image; a tap opensdata.link_urlwhen present — handle that key in your FCM service. - Windows: there is no push channel, so poll
GET https://bytemaple.com/api/notifications?install_id=…&app=…on start (and at most hourly). Each campaign is returned once — the call itself marks it delivered. Show it as an in-app notice; openlink_urlin the browser on click. countryis the ISO 2-letter code, optional — used only for aggregate statistics.
8. Good practice
- Never hard-code a license key in the app binary; keys belong to users.
- Treat network failures as “keep the last known state”, not as “expired”.
- Rate limits: the API allows 60 requests per minute per client — the cadence above is far below it.
- Developers of a covered product can see the privacy wording for licenses and push on that product's privacy page, e.g. https://bytemaple.com/privacy/ludo-strike.