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 and accepted_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, or updatedDate.

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, or licenseKey (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, or updatedAt.

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 of accepted_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