Skip to main content

max / makenotwork

6.2 KB · 243 lines History Blame Raw
1 # License Key API Guide
2
3 The License Key API lets software applications validate and manage license keys issued through Makenot.work. All endpoints are public (no authentication required) and rate-limited.
4
5 Endpoints are available at both `/api/keys/` and `/api/v1/keys/` paths. New integrations should use the `/api/v1/` prefix.
6
7 ## Validate and Activate a Key
8
9 Validates a license key and optionally activates it on a machine.
10
11 ```
12 POST https://makenot.work/api/v1/keys/validate
13 Content-Type: application/json
14
15 {
16 "key": "XXXX-XXXX-XXXX-XXXX",
17 "machine_id": "unique-machine-identifier",
18 "label": "Alice's MacBook Pro"
19 }
20 ```
21
22 ### Parameters
23
24 | Field | Required | Description |
25 |-------|----------|-------------|
26 | `key` | Yes | The license key string |
27 | `machine_id` | Yes | A stable, unique identifier for this machine |
28 | `label` | No | Human-readable name for this activation |
29
30 ### Response
31
32 ```json
33 {
34 "valid": true,
35 "activated": true,
36 "license": {
37 "item_id": "550e8400-...",
38 "max_activations": 3,
39 "activation_count": 1,
40 "created_at": "2026-03-13T10:00:00Z"
41 }
42 }
43 ```
44
45 ### Error Cases
46
47 ```json
48 {
49 "valid": false,
50 "error": "invalid_key"
51 }
52 ```
53
54 | Error | Meaning |
55 |-------|---------|
56 | `invalid_key` | Key does not exist |
57 | `key_revoked` | Key has been revoked by the creator |
58 | `activation_limit_reached` | All activation slots are in use |
59
60 ### Idempotent Activation
61
62 If the same `key` + `machine_id` combination is submitted again, the existing activation is refreshed (timestamp updated) without consuming an additional slot.
63
64 ## Check Key Status
65
66 Check whether a key is valid without activating it.
67
68 ```
69 GET https://makenot.work/api/v1/keys/{key_code}/status
70 ```
71
72 Response:
73
74 ```json
75 {
76 "valid": true,
77 "license": {
78 "item_id": "550e8400-...",
79 "max_activations": 3,
80 "activation_count": 2,
81 "remaining_activations": 1,
82 "created_at": "2026-03-13T10:00:00Z"
83 }
84 }
85 ```
86
87 Use this for periodic license checks without affecting activation state.
88
89 ## Deactivate a Key
90
91 Release an activation slot (e.g., when the user uninstalls your software).
92
93 ```
94 POST https://makenot.work/api/v1/keys/deactivate
95 Content-Type: application/json
96
97 {
98 "key": "XXXX-XXXX-XXXX-XXXX",
99 "machine_id": "unique-machine-identifier"
100 }
101 ```
102
103 Response:
104
105 ```json
106 {
107 "success": true,
108 "message": "Activation removed"
109 }
110 ```
111
112 ## License Verification (Offline Grace Period)
113
114 For apps that need to work offline, use the verification endpoint. It validates and activates the key, then returns a signed JWT token valid for 7 days. Your app can verify this token locally without contacting the server.
115
116 This endpoint requires the project to have license verification enabled (configured by the creator in project settings).
117
118 ```
119 POST https://makenot.work/api/v1/license/verify
120 Content-Type: application/json
121
122 {
123 "key": "XXXX-XXXX-XXXX-XXXX",
124 "machine_fingerprint": "unique-machine-identifier"
125 }
126 ```
127
128 ### Response
129
130 ```json
131 {
132 "valid": true,
133 "token": "eyJhbGciOiJIUzI1NiIs...",
134 "expires_in": 604800
135 }
136 ```
137
138 | Field | Description |
139 |-------|-------------|
140 | `valid` | Whether the key is valid and activated |
141 | `token` | Signed JWT for offline verification (7-day validity) |
142 | `expires_in` | Token lifetime in seconds (604800 = 7 days) |
143
144 ### JWT Claims
145
146 The token contains:
147
148 | Claim | Description |
149 |-------|-------------|
150 | `sub` | License key ID |
151 | `machine` | Machine fingerprint |
152 | `item` | Item ID |
153 | `iat` | Issued at (Unix timestamp) |
154 | `exp` | Expires at (Unix timestamp) |
155
156 ### Offline Flow
157
158 1. Call `/api/v1/license/verify` on app launch (when online)
159 2. Cache the returned JWT locally
160 3. On subsequent launches, verify the JWT signature and `exp` claim locally
161 4. Re-verify with the server when the token nears expiry or when connectivity returns
162
163 ### Deactivation via Verify API
164
165 ```
166 POST https://makenot.work/api/v1/license/deactivate
167 Content-Type: application/json
168
169 {
170 "key": "XXXX-XXXX-XXXX-XXXX",
171 "machine_fingerprint": "unique-machine-identifier"
172 }
173 ```
174
175 | Error | Meaning |
176 |-------|---------|
177 | `invalid_key` | Key does not exist |
178 | `key_revoked` | Key has been revoked by the creator |
179 | `activation_limit_reached` | All activation slots are in use |
180 | `verification_not_enabled` | Project does not have license verification enabled |
181
182 ## License Text
183
184 Retrieve the license agreement for an item in plain text:
185
186 ```
187 GET https://makenot.work/api/v1/items/{item_id}/license.txt
188 ```
189
190 Returns the license text configured by the creator (MIT, Apache 2.0, custom, etc.) as `text/plain`.
191
192 ## Revocation
193
194 Creators can revoke keys from their dashboard. A revoked key returns `key_revoked` on all endpoints and cannot be reactivated.
195
196 ## PWYW Compatibility
197
198 License keys work with Pay What You Want (PWYW) items. Any customer who completes a purchase receives a key if the creator has keys enabled.
199
200 ## Machine ID Guidelines
201
202 The `machine_id` (or `machine_fingerprint` for the verify API) should be:
203 - **Stable**: Same value across app restarts and updates
204 - **Unique**: Different on each machine
205 - **Not personally identifiable**: Avoid using MAC addresses or usernames
206
207 Good approaches:
208 - Generate a UUID on first launch and store it in the app's data directory
209 - Use a hardware-derived hash (disk serial, motherboard ID)
210 - Use the OS machine ID (e.g., `/etc/machine-id` on Linux)
211
212 ## Rate Limits
213
214 License key endpoints are rate-limited per IP. See [API Overview]./api-overview.md for current limits.
215
216 ## Integration Pattern
217
218 Recommended flow for desktop applications:
219
220 1. **On first launch**: Prompt for license key, call `/api/v1/keys/validate` with a generated machine ID
221 2. **On subsequent launches**: Call `/api/v1/license/verify` for offline-capable apps, or `/api/v1/keys/{key_code}/status` for online-only apps
222 3. **On uninstall**: Call `/api/v1/keys/deactivate` to release the activation slot
223 4. **On activation failure**: Show the error message and allow the user to enter a different key
224
225 ## Error Response Format
226
227 ```json
228 {
229 "error": "descriptive message"
230 }
231 ```
232
233 | Status | Meaning |
234 |--------|---------|
235 | 400 | Invalid request body |
236 | 404 | Key not found (for status endpoint) |
237 | 429 | Rate limit exceeded |
238
239 ## See Also
240
241 - [Pricing & Monetization]../guide/03-selling.md: License key setup for creators
242 - [API Overview]./api-overview.md: Authentication and rate limits
243