API v2
API v2 provides a full RESTful interface for managing licenses, products, customers, and blacklists. All endpoints (except health check) require API token authentication.
Authentication & Intents
- API Token: All endpoints (except
/healthy) require an API token in the request header:TOKEN: <your-api-token>
- Intents: Each endpoint requires specific intents. If your token lacks the required intent, you will receive an error response with a list of accepted intents.
Error Handling
All error responses follow this structure:
{
"message": "invalid token or missing required intent",
"accepted_intents": ["PRODUCTS_READ", "PRODUCTS_READ_WRITE", ...]
}- Always check the
messageandaccepted_intentsfields to understand why a request failed.
Update (PUT) Operations Warning
Important:
For every update (PUT) call, always perform a GET first and pass all fields (including unchanged ones) in your PUT request. Fields not included in the PUT body may be lost.
Endpoints
1. Health & Ping
GET /api/v2/healthy
- Description: Health check endpoint. No authentication required.
- Response:
200 OK—"healthy"
GET /api/v2/ping
- Description: Ping endpoint to test authentication.
- Headers:
TOKEN: <api-token>
- Response:
200 OK—"pong"401 Unauthorized— Error response
2. Product API
GET /api/v2/products
- Intents:
PRODUCTS_READ,PRODUCTS_READ_WRITE,ALL_READ,ALL_READ_WRITE - Response: List of products
GET /api/v2/products/{id}
- Intents: Same as above
- Response: Product object
POST /api/v2/products
- Intents:
PRODUCTS_READ_WRITE,ALL_READ_WRITE - Body:
{
"name": "Test Product",
"description": "My product description",
"productType": "OTHER",
"productTypeOther": "Custom Type",
"defaultMaxIPs": 4,
"defaultMaxHWIDs": 3
}- Note: Do not include
id,createdDate, orupdatedDate.
PUT /api/v2/products/{id}
- Intents: Same as POST
- Body: All product fields (see GET response)
- Warning: See update warning above.
DELETE /api/v2/products/{id}
- Intents: Same as POST
Sample Product Response:
{
"id": 1,
"name": "Test Product",
"description": "My product description",
"productType": "OTHER",
"productTypeOther": "Custom Type",
"createdDate": "2025-01-01T00:00:00.000+00:00",
"updatedDate": "2025-01-01T00:00:00.000+00:00",
"defaultMaxIPs": 4,
"defaultMaxHWIDs": 3,
"roleId": null,
"purchaseRoleId": null,
"url": null,
"imageUrl": null
}3. License API
GET /api/v2/licenses
- Intents:
LICENSES_READ,LICENSES_READ_WRITE,ALL_READ,ALL_READ_WRITE
GET /api/v2/licenses/{id}
- Intents: Same as above
POST /api/v2/licenses
- Intents:
LICENSES_READ_WRITE,ALL_READ_WRITE - Body:
{
"productId": 1,
"licenseType": "TEMPORARY",
"licensePlatform": null,
"licensePlatformOther": "",
"ownerPlatformId": "",
"expiryDate": "2026-12-31T23:59:59.000+00:00",
"maxIPs": 5,
"maxHWIDs": 5,
"ownerDiscordId": "",
"ownerDiscordUsername": "",
"notes": ""
}- Note: Do not include
id,createdDate,updatedDate,customer, orlicenseKey(license key is generated automatically).
GET /api/v2/licenses/by-license-key/{licenseKey}
- Intents: Same as above
- Description: Get a single license by its license key
- Response: License object or 404 if not found
GET /api/v2/licenses/by-customer-email/{email}
- Intents: Same as above
- Description: Get all licenses associated with a customer email address
- Response: Array of license objects
GET /api/v2/licenses/by-platform/{platform}/{platformId}
- Intents: Same as above
- Description: Get all licenses for a specific platform and platform ID
- Query Parameters:
productId(optional): Filter by product ID
- Path Parameters:
platform: One of SPIGOT, FORGE, BUKKIT, BUILT_BY_BIT, SOURCE_EXCHANGE, DISCORD, OTHERplatformId: The platform-specific user ID
- Response: Array of license objects
GET /api/v2/licenses/by-customer-id/{customerId}
- Intents: Same as above
- Description: Get all licenses for a specific customer ID
- Response: Array of license objects
GET /api/v2/licenses/by-product-id/{productId}
- Intents: Same as above
- Description: Get all licenses for a specific product
- Response: Array of license objects
GET /api/v2/licenses/by-discord-id/{discordId}
- Intents: Same as above
- Description: Get all licenses associated with a Discord user ID
- Response: Array of license objects
PUT /api/v2/licenses/{id}
- Intents: Same as POST
- Body: All license fields (see GET response)
- Warning: See update warning above.
DELETE /api/v2/licenses/{id}
- Intents: Same as POST
Sample License Response:
{
"id": 1,
"licenseKey": "ABCD1234EFGH5678IJKL",
"productId": 1,
"licenseType": "TEMPORARY",
"licensePlatform": null,
"licensePlatformOther": "",
"ownerPlatformId": "",
"createdDate": "2025-01-01T00:00:00.000+00:00",
"updatedDate": "2025-06-01T00:00:00.000+00:00",
"expiryDate": "2026-12-31T23:59:59.000+00:00",
"maxIPs": 5,
"maxHWIDs": 5,
"totalRequests": null,
"ownerDiscordId": "",
"ownerDiscordUsername": "",
"licenseStatus": "ACTIVE",
"hwids": [],
"ips": [],
"notes": "",
"customer": { ... },
"productIdString": "1"
}4. Blacklist API
GET /api/v2/blacklists
- Intents:
BLACKLISTS_READ,BLACKLISTS_READ_WRITE,ALL_READ,ALL_READ_WRITE
GET /api/v2/blacklists/{id}
- Intents: Same as above
POST /api/v2/blacklists
- Intents:
BLACKLISTS_READ_WRITE,ALL_READ_WRITE - Body:
{
"licenseDataType": "HWID",
"data": "unique-hardware-id",
"isForAllProducts": true,
"reason": "Fraudulent activity"
}- Note: Do not include
id,createdAt, orupdatedAt.
PUT /api/v2/blacklists/{id}
- Intents: Same as POST
- Body: All blacklist fields (see GET response)
- Warning: See update warning above.
DELETE /api/v2/blacklists/{id}
- Intents: Same as POST
Sample Blacklist Response:
{
"id": 1,
"licenseDataType": "HWID",
"data": "unique-hardware-id",
"isForAllProducts": true,
"productId": null,
"reason": "Fraudulent activity",
"createdAt": "2025-02-01T00:00:00.000+00:00",
"updatedAt": "2025-02-01T00:00:00.000+00:00"
}5. License Request API
GET /api/v2/requests
- Intents:
REQUESTS_READ,ALL_READ,ALL_READ_WRITE
GET /api/v2/requests/{id}
- Intents: Same as above
Sample License Request Response:
{
"id": 1,
"licenseId": null,
"licenseKey": "ABCD1234EFGH5678IJKL",
"productId": 1,
"productVersion": "1.0.0",
"ip": "192.168.1.1",
"hwid": "unique-hardware-id",
"macAddress": "00:1A:2B:3C:4D:5E",
"operatingSystem": "Windows",
"operatingSystemVersion": "10",
"operatingSystemArchitecture": "x64",
"javaVersion": "17",
"requestDate": "2025-06-01T12:00:00.000+00:00",
"requestType": "Valid",
"responseType": "Success",
"blockReason": null,
"notes": null,
"remarks": null,
"valid": true,
"successful": true,
"rateLimited": false,
"blocked": false,
"spam": false
}6. Customer API
GET /api/v2/customers
- Intents:
CUSTOMERS_READ,ALL_READ,ALL_READ_WRITE
GET /api/v2/customers/{id}
- Intents: Same as above
Sample Customer Response:
{
"id": 1,
"firstName": null,
"lastName": null,
"username": "customer_user",
"email": null,
"phoneNumber": null,
"profilePictureUrl": null,
"passwordHash": null,
"role": null,
"status": null,
"createdAt": null,
"lastLoginAt": null,
"discordId": null,
"discordUsername": null,
"discordAvatarUrl": null,
"discordAccessToken": null,
"discordRefreshToken": null,
"discordTokenExpiry": null,
"spigotId": null,
"spigotUsername": null,
"forgeId": null,
"forgeUsername": null,
"bukkitId": null,
"bukkitUsername": null,
"builtByBitId": null,
"builtByBitUsername": null,
"sourceExchangeId": null,
"sourceExchangeUsername": null
}7. License Validation API
POST /api/v2/validate
- Intents:
LICENSE_VALIDATE,ALL_READ_WRITE - Body: See v1 LicenseRequestController for request structure.
- Response: Same as v1 LicenseRequestController.
Enum Values
ProductType
| Value | Description |
|---|---|
MINECRAFT_JAVA_PLUGIN | Bukkit/Spigot/Paper plugin |
MINECRAFT_JAVA_MOD | Forge/Fabric mod |
MINECRAFT_BEDROCK_PLUGIN | Bedrock Edition plugin |
MINECRAFT_BEDROCK_MOD | Bedrock Edition mod |
MINECRAFT_SERVER_SETUP | Server setup/configuration |
WEB_APPLICATION | Web app or API |
DESKTOP_APPLICATION | Desktop software |
MOBILE_APPLICATION | Mobile app |
OTHER | Other product type |
LicenseType
| Value | Description |
|---|---|
TEMPORARY | Time-limited license |
PERMANENT | Never expires |
LicenseStatus
| Value | Description |
|---|---|
ACTIVE | License is valid |
EXPIRED | Past expiry date |
DEACTIVATED | Manually deactivated |
DELETED | Soft-deleted |
LicensePlatform
| Value | Description |
|---|---|
SPIGOT | SpigotMC |
FORGE | Minecraft Forge |
BUKKIT | Bukkit |
BUILT_BY_BIT | BuiltByBit |
SOURCE_EXCHANGE | SourceExchange |
DISCORD | Discord |
OTHER | Other platform |
LicenseDataType (Blacklist)
| Value | Description |
|---|---|
IP | IP address |
HWID | Hardware ID |
ApiIntent
| Intent | Permission |
|---|---|
PRODUCTS_READ | Read products |
PRODUCTS_READ_WRITE | Read and write products |
LICENSE_VALIDATE | Validate licenses |
LICENSES_READ | Read licenses |
LICENSES_READ_WRITE | Read and write licenses |
BLACKLISTS_READ | Read blacklist entries |
BLACKLISTS_READ_WRITE | Read and write blacklist entries |
REQUESTS_READ | Read license request history |
CUSTOMERS_READ | Read customers |
ALL_READ | Read everything |
ALL_READ_WRITE | Full access to everything |
General Notes
- Always include the
TOKENheader for all endpoints except/healthy. - For all update (PUT) operations, always fetch the current object first and send all fields in your update request.
- Error responses will always include a
messageand a list ofaccepted_intents. - Do not send fields like
id,createdDate,updatedDate, or system-generated fields when creating new objects. - For creating licenses, do not send the license key or customer object; these are handled by the system.
For further details or questions, visit the GitHub repository.
