Skip to content

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:

json
{
  "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:
json
{
  "name": "Test Product",
  "description": "My product description",
  "productType": "OTHER",
  "productTypeOther": "Custom 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:

json
{
  "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:
json
{
  "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, or licenseKey (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, OTHER
    • platformId: 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:

json
{
  "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:
json
{
  "licenseDataType": "HWID",
  "data": "unique-hardware-id",
  "isForAllProducts": true,
  "reason": "Fraudulent activity"
}
  • 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:

json
{
  "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:

json
{
  "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:

json
{
  "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

ValueDescription
MINECRAFT_JAVA_PLUGINBukkit/Spigot/Paper plugin
MINECRAFT_JAVA_MODForge/Fabric mod
MINECRAFT_BEDROCK_PLUGINBedrock Edition plugin
MINECRAFT_BEDROCK_MODBedrock Edition mod
MINECRAFT_SERVER_SETUPServer setup/configuration
WEB_APPLICATIONWeb app or API
DESKTOP_APPLICATIONDesktop software
MOBILE_APPLICATIONMobile app
OTHEROther product type

LicenseType

ValueDescription
TEMPORARYTime-limited license
PERMANENTNever expires

LicenseStatus

ValueDescription
ACTIVELicense is valid
EXPIREDPast expiry date
DEACTIVATEDManually deactivated
DELETEDSoft-deleted

LicensePlatform

ValueDescription
SPIGOTSpigotMC
FORGEMinecraft Forge
BUKKITBukkit
BUILT_BY_BITBuiltByBit
SOURCE_EXCHANGESourceExchange
DISCORDDiscord
OTHEROther platform

LicenseDataType (Blacklist)

ValueDescription
IPIP address
HWIDHardware ID

ApiIntent

IntentPermission
PRODUCTS_READRead products
PRODUCTS_READ_WRITERead and write products
LICENSE_VALIDATEValidate licenses
LICENSES_READRead licenses
LICENSES_READ_WRITERead and write licenses
BLACKLISTS_READRead blacklist entries
BLACKLISTS_READ_WRITERead and write blacklist entries
REQUESTS_READRead license request history
CUSTOMERS_READRead customers
ALL_READRead everything
ALL_READ_WRITEFull access to everything

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, visit the GitHub repository.

Released under the MIT License.