API documentation
A JSON REST API for the marketplace, plus the licence verification endpoints authors embed in their own software. Every response uses the same envelope, and result codes are a stable contract — you can branch on them safely.
Base URL
https://mitrait.in/api/v1
Licence verification
The endpoints you embed in your own software. They are unauthenticated by design — a deployed customer application holds a purchase code, not a marketplace token — and are rate limited per IP and per licence key.
/license/verify
Check a licence without changing activation state.
Request body
{
"license_key": "SMKT-8F72-29KD-4B1P",
"product_id": 12,
"domain": "customer-site.com"
}
/license/activate
Bind a licence to an installation. Re-activating the same host is free.
Request body
{
"license_key": "SMKT-8F72-29KD-4B1P",
"domain": "customer-site.com",
"environment": "production"
}
/license/deactivate
Release an installation and return its activation slot.
Request body
{
"license_key": "SMKT-8F72-29KD-4B1P",
"domain": "customer-site.com"
}
/license/status
Current status and entitlement windows for a licence.
Request body
{
"license_key": "SMKT-8F72-29KD-4B1P"
}
/license/{key}/updates
Whether a newer version is available to this licence holder.
Catalogue (public)
Read-only catalogue access. No token required.
/products
List published products. Supports q, category, type, framework, free, author, min_rating, sort, per_page.
/products/{slug}
Full detail for one product, including licence options.
/categories
The full category tree with product counts.
/categories/{slug}
One category with its products.
/authors
List approved authors.
/authors/{slug}
One author with their catalogue.
Account (token required)
Send your token as Authorization: Bearer <token>. Create tokens under Account → API tokens.
/auth/token
Exchange credentials for a token. Blocked for accounts with 2FA — create those from the account settings screen.
Request body
{
"email": "you@example.com",
"password": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
"device_name": "ci-pipeline"
}
/auth/me
Who this token belongs to, and what it can do.
/me/purchases
Your purchase history.
/me/licenses
Your licences, with entitlement windows and activation counts.
/me/downloads
Your download history.
/downloads/{file}/url
Mint a short-lived signed download URL after an entitlement check.
/wallet
Wallet balances.
/wallet/transactions
Wallet statement, with the correlation reference on every row.
Result codes
Licence endpoints answer 200 whenever the request was understood — including
when the verdict is "invalid". Branch on code, not on the HTTP status, so you
can tell "this licence is not valid" apart from "my integration is broken".
| Code | Meaning |
|---|---|
valid
|
The licence is valid and, where applicable, activated for this installation. |
invalid
|
The key is not recognised, or does not belong to the product supplied. |
expired
|
The licence has passed its expiry date. |
revoked
|
The licence was revoked, refunded or suspended. |
activation_limit_reached
|
No activation slots remain. The holder must deactivate an installation first. |
domain_mismatch
|
This installation is not activated for the supplied licence. |
product_disabled
|
The marketplace has disabled this product. |
not_activated
|
The product requires activation and no identifier was supplied. |
activation_not_required
|
This product does not use activation; the key alone is sufficient. |
Response envelope
{
"success": true,
"code": "valid",
"message": "License is valid.",
"data": {
"license_key": "SMKT-8F72-29KD-4B1P",
"product": {
"id": 12,
"name": "Android Recharge App",
"version": "2.1.0"
},
"license_type": "Regular License",
"status": "active",
"buyer": {
"name": "Anita Sharma",
"email": "anita@example.com"
},
"purchased_version": "2.0.0",
"support_active": true,
"supported_until": "2026-08-08T00:00:00+05:30",
"updates_active": true,
"updates_until": null,
"activation_mode": "domain",
"activation_limit": 1,
"activations_used": 1,
"activations_remaining": 0
}
}
A null in updates_until or supported_until means
lifetime, not "unknown".
Integration examples
Verify on install and then periodically — not on every request. Cache the result and fail open on a network error, so a marketplace outage never takes your customer's site down.
<?php
function verifyLicense(string $key, string $domain): array
{
$ch = curl_init('https://mitrait.in/api/v1/license/verify');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Accept: application/json'],
CURLOPT_POSTFIELDS => json_encode([
'license_key' => $key,
'domain' => $domain,
]),
]);
$body = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
// Fail open on a network problem: an outage on our side must not
// take the customer's installation offline.
if ($error || $body === false) {
return ['success' => true, 'code' => 'offline_grace', 'message' => $error];
}
return json_decode($body, true) ?? ['success' => false, 'code' => 'invalid'];
}
$result = verifyLicense(getenv('LICENSE_KEY'), $_SERVER['HTTP_HOST']);
if (! $result['success']) {
exit('Licence problem: ' . $result['message']);
}
const BASE = 'https://mitrait.in/api/v1';
export async function verifyLicense(key, domain) {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 10_000);
try {
const response = await fetch(`${BASE}/license/verify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
body: JSON.stringify({ license_key: key, domain }),
signal: controller.signal,
});
return await response.json();
} catch (error) {
// Fail open — never hard-block on a transient network fault.
return { success: true, code: 'offline_grace', message: error.message };
} finally {
clearTimeout(timeout);
}
}
# Verify
curl -X POST https://mitrait.in/api/v1/license/verify \
-H "Content-Type: application/json" \
-d '{"license_key":"SMKT-8F72-29KD-4B1P","domain":"customer-site.com"}'
# Activate
curl -X POST https://mitrait.in/api/v1/license/activate \
-H "Content-Type: application/json" \
-d '{"license_key":"SMKT-8F72-29KD-4B1P","domain":"customer-site.com"}'
# Authenticated call
curl https://mitrait.in/api/v1/me/licenses \
-H "Authorization: Bearer mk_xxxxxxxx_yyyyyyyyyyyy" \
-H "Accept: application/json"
Errors & rate limits
| Status | When it happens |
|---|---|
200 |
Request understood. Check the "code" field for the verdict. |
401 |
Missing or invalid API token. |
403 |
Token lacks the required ability, is IP-restricted, or the account is inactive. |
404 |
No such resource, or it is not published. |
422 |
Validation failed — the response lists the offending fields. |
429 |
Rate limit exceeded. Back off and retry after the Retry-After header. |
500 |
Something broke on our side. Retry with backoff; if it persists, contact support. |
Rate limits
- Licence endpoints: 120 requests per minute per IP, and 30 per minute per licence key.
- Public catalogue: 60 requests per minute per IP.
- Authenticated endpoints: 60 per minute by default, configurable per token.