API V2
SunLicense API V2 provides a secure, RESTful interface for managing products, licenses, blacklists, license requests, and customers.
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
message
andaccepted_intents
fields 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": "1",
"productType": "OTHER",
"productTypeOther": "Test 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": 602,
"name": "Test Product",
"description": "1",
"productType": "OTHER",
"productTypeOther": "Test Type",
"createdDate": "2024-11-16T09:54:23.048+00:00",
"updatedDate": "2024-11-16T09:54:23.048+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": 1552,
"licenseType": "TEMPORARY",
"licensePlatform": null,
"licensePlatformOther": "",
"ownerPlatformId": "",
"expiryDate": "2025-05-31T18:30:00.000+00:00",
"maxIPs": 5,
"maxHWIDs": 5,
"ownerDiscordId": "754054589690544250",
"ownerDiscordUsername": "kaxun",
"notes": ""
}
Note: Do not include
id
,createdDate
,updatedDate
,customer
, orlicenseKey
(license key is generated automatically).
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": 4353,
"licenseKey": "U12BPHB1VO1CB73N773B",
"productId": 1552,
"licenseType": "TEMPORARY",
"licensePlatform": null,
"licensePlatformOther": "",
"ownerPlatformId": "",
"createdDate": "2025-06-15T15:00:37.243+00:00",
"updatedDate": "2025-06-23T05:31:36.707+00:00",
"expiryDate": "2025-05-31T18:30:00.000+00:00",
"maxIPs": 5,
"maxHWIDs": 5,
"totalRequests": null,
"ownerDiscordId": "754054589690544250",
"ownerDiscordUsername": "kaxun",
"licenseStatus": "EXPIRED",
"hwids": [],
"ips": [],
"notes": "",
"customer": { ... },
"productIdString": "1552"
}
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-id3",
"isForAllProducts": true,
"reason": "x"
}
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-id3",
"isForAllProducts": true,
"productId": null,
"reason": "x",
"createdAt": "2025-02-13T07:41:53.226+00:00",
"updatedAt": "2025-02-13T07:41:53.226+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": 802,
"licenseId": null,
"licenseKey": "FE72URFX4RKWM38T0ARO",
"productId": 602,
"productVersion": "1.0.0",
"ip": "0:0:0:0:0:0:0:1",
"hwid": "unique-hardware-id7",
"macAddress": "00:1A:2B:3C:4D:5E",
"operatingSystem": "Windows",
"operatingSystemVersion": "10",
"operatingSystemArchitecture": "x64",
"javaVersion": "17",
"requestDate": "2025-01-27T17:28:13.173+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": 503,
"firstName": null,
"lastName": null,
"username": "chinezu_1221",
"email": null,
"phoneNumber": null,
"profilePictureUrl": "https://cdn.discordapp.com/avatars/1203762369625464832/a_7a39928788f5ee51dd60b53a8f04ed4a.gif",
"passwordHash": null,
"role": null,
"status": null,
"createdAt": null,
"lastLoginAt": null,
"discordId": 1203762369625464832,
"discordUsername": "chinezu_1221",
"discordAvatarUrl": null,
"discordAccessToken": null,
"discordRefreshToken": null,
"discordTokenExpiry": null,
"spigotId": null,
"spigotUsername": null,
"forgeId": null,
"forgeUsername": null,
"bukkitId": null,
"bukkitUsername": null,
"builtByBitId": "477048",
"builtByBitUsername": null,
"sourceExchangeId": null,
"sourceExchangeUsername": null,
"ploymartId": null,
"ploymartUsername": null,
"modrinthId": null,
"modrinthUsername": null,
"curseforgeId": null,
"curseforgeUsername": null,
"notes": 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 Used in API Models
ProductType (Product)
MINECRAFT_JAVA_PLUGIN
MINECRAFT_JAVA_MOD
MINECRAFT_BEDROCK_PLUGIN
MINECRAFT_BEDROCK_MOD
MINECRAFT_SERVER_SETUP
WEB_APPLICATION
DESKTOP_APPLICATION
MOBILE_APPLICATION
OTHER
LicenseType (License)
TEMPORARY
PERMANENT
LicenseStatus (License)
ACTIVE
EXPIRED
DEACTIVATED
DELETED
LicensePlatform (License)
SPIGOT
FORGE
BUKKIT
BUILT_BY_BIT
SOURCE_EXCHANGE
DISCORD
OTHER
LicenseDataType (Blacklist)
IP
HWID
ApiIntent (Token/Permissions)
PRODUCTS_READ
PRODUCTS_READ_WRITE
LICENSE_VALIDATE
LICENSES_READ
LICENSES_READ_WRITE
BLACKLISTS_READ
BLACKLISTS_READ_WRITE
REQUESTS_READ
CUSTOMERS_READ
ALL_READ
ALL_READ_WRITE
General Notes
Always include the
TOKEN
header 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
message
and 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, contact the SunLicense support team.
Last updated