This is a community guide for authors who want to implement purchase code verification on their items, websites, and applications. If you have any questions or feedback then please feel free to respond directly to this topic.
This topic is a wiki. All active members of the forums can edit it. Don’t hesitate to make corrections or add in any new information. All contributions are welcome!
Just want some working code to get started quickly?
- There are some functional code examples listed at the bottom of the guide.
- There are also several unofficial libraries that you can quickly install into your project.
Be sure to check out the official documentation for the API as well!
Table of contents
- Authentication
- Sending requests
- Handling responses
- Testing your code
- Code examples
- Libraries
- Plugins & scripts
Authentication
Create a personal token
You need a “personal token” before you can validate purchase codes for your items. This is similar to a password that grants limited access to your account, but it’s exclusively for the API.
- Go to https://build.envato.com/create-token/ (sign in if prompted).
For purchase code verification you must select the following permissions (see this screenshot):
- View and search Envato sites (selected by default)
- View the user’s items’ sales history
After creating the token, copy and save it somewhere. Envato won’t show the token to you again.
Secure your personal token
Your personal token is like a password that grants limited access to your account. You need to keep it private and secure.
- Don’t hardcode the personal token into your items.
- Don’t share the token with anyone outside of your team.
If you ever believe a personal token has been compromised or accidentally made public, delete it at build.envato.com and create another.
Sending requests
There are some gotcha’s with the Envato API, so please read this section carefully – especially the “caution!” admonitions.
Validate user input
When accepting purchase codes from user input, you should trim (remove surrounding spaces) and validate (with a regular expression) the codes to ensure they are in the correct format. Envato generates purchase codes with UUID v4. You can validate with the following expression.
(If you’re not familiar with regular expressions and the below looks illegible to you, check out the PHP code examples further down to see how you might use it in practice.)
/^([a-f0-9]{8})-(([a-f0-9]{4})-){3}([a-f0-9]{12})$/i
Caution! If you attempt to look up a purchase code that is formatted incorrectly, the request will be blocked with a
403
response. The response body may also not contain valid JSON, which could break your code. Check the format with the above expression to avoid this situation altogether.
Send the purchase code
The request to look up a purchase code is as follows:
GET https://api.envato.com/v3/market/author/sale?code=PURCHASE_CODE_HERE
Authorization: Bearer YOUR_PERSONAL_TOKEN_HERE
User-Agent: Purchase code verification
Add your personal token that you generated at build.envato.com into the Authorization
header. The final result will look like this:
Authorization: Bearer s6IscWrJL3NsBnqvUy6Q3XiImvcZlwkn
Your user agent should briefly describe your application. This will be visible to the Envato Team and can help them manage your rate limit. Some examples:
User-Agent: Purchase code verification
User-Agent: themefusion.com support forums
Caution! Do not use a browser user agent for these requests. Those experienced with web scraping may feel inclined to use a browser agent out of habit. However, doing so in this case may render your requests blocked, as these API requests should never come from browsers.
Click to see an example of a browser agent
// Don't use this or you could get blocked! User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Handling responses
Valid purchase codes
For purchase codes that are valid and belong to one of your buyers, the response will look like this:
{
"amount": "19.84",
"sold_at": "2016-09-07T10:54:28+10:00",
"license": "Regular License",
"support_amount": "0.00",
"supported_until": "2017-03-09T01:54:28+11:00",
"item": {
"id": 17022701,
"name": "SEO Studio - Professional Tools for SEO",
"description": "<strong>Full</strong> HTML description here...",
"author_username": "baileyherbert",
"updated_at": "2017-11-02T15:57:41+11:00",
"site": "codecanyon.net",
"price_cents": 2000,
"published_at": "2016-07-13T19:07:03+10:00"
},
"buyer": "buyer_username_or_null",
"purchase_count": 1
}
Caution! For purchases made before 2018, it was possible for buyers to check out as a guest, in which case the
buyer
field in the above response would benull
. Guest checkout is no longer an option so this does not apply to newer items.
Invalid purchase codes
If the purchase code is formatted correctly but does not exist (or does not belong to one of your buyers), the response will look like this:
{
"error": 404,
"description": "No sale belonging to the current user found with that code"
}
If the purchase code was formatted incorrectly, you will get a 403
response from Cloudflare with the following plaintext content. You should validate the format of the purchase code to avoid this.
error code: 1020
Banned accounts
It’s worth mentioning that if a buyer’s account is suspended or banned by Envato then their purchase codes will return the above 404
error and can no longer be validated. In these cases, it’s no longer possible for the buyer to validate their purchase.
Refunded purchases
If you ever refund a purchase, then similar to banned accounts, the corresponding purchase code will return the above 404
error and can no longer be validated. The same is automatically true for sale reversals and refunds manually issued by Envato Support.
List of status codes
- 200 – Purchase code is valid.
- 404 – Purchase code was not found (or) did not belong to one of your items.
-
403 – Your personal token is incorrect or is missing the required permission.
- It could also mean the purchase code is formatted incorrectly or has surrounding whitespace.
-
401 – The
authorization
header is missing or not in the correct format.
Testing your code
There is no official sandbox for testing your script at this time. However, I’ve created my own personal sandbox and you’re more than welcome to use it. You can find the source code here.
Change the URL in your script to the following:
https://sandbox.bailey.sh/v3/market/author/sale?code=
You must also use the following personal token for this sandbox via the Authorization
header:
cFAKETOKENabcREPLACEMExyzcdefghj
This fake token is now required for the sandbox to work, and is used to help you ensure you’re setting the authorization header correctly. If you send this token in the wrong format, you’ll receive a very helpful error with guidance on what you did wrong.
WARNING! Please make sure you don’t accidentally send your real personal token to this sandbox. If you do send a realistic-looking token, the sandbox will return a
403
error and the body will alert you about the mistake, in this case please delete the token at build.envato.com and generate another one to be safe.
Now test your script with the following valid purchase code:
-
Valid purchase code –
86781236-23d0-4b3c-7dfa-c1c147e0dece
For a positive user experience, please test your script with these purchase codes as well. These will cause different kinds of errors, so make sure your script handles them properly.
-
Invalid purchase code –
94252c00-df24-4cf5-99dd-49fc17e23043
-
Improper code –
02b6429f-9274-9a70-03ce49bc5a48
- Valid code with whitespace – Try using the valid purchase code above, but add some spaces before and/or after it to make sure that you’re trimming it correctly.
After you’ve confirmed that your code is working, revert your script to the official URL and your real personal token. You can test that everything is working by sending the following request to the real API – you will receive a 404
error if everything is correct.
https://api.envato.com/v3/market/author/sale?code=86781236-23d0-4b3c-7dfa-c1c147e0dece
Code examples
PHP (Function)
This ready-to-go function accepts the purchase code as its sole argument and returns a parsed object. It will throw an exception if the code is incorrect, or if there was an unexpected issue.
Replace the YOUR_PERSONAL_TOKEN_HERE
on line 2 with your personal token.
Note: Don’t put this code inside your item. Instead, place it on your own server, and have your item communicate with your server instead. This is required to keep your personal token secure – it’s like a password for your account.
function getPurchaseCode($code) {
$personalToken = "YOUR_PERSONAL_TOKEN_HERE";
// Surrounding whitespace can cause a 404 error, so trim it first
$code = trim($code);
// Make sure the code looks valid before sending it to Envato
// This step is important - requests with incorrect formats can be blocked!
if (!preg_match("/^([a-f0-9]{8})-(([a-f0-9]{4})-){3}([a-f0-9]{12})$/i", $code)) {
throw new Exception("Invalid purchase code");
}
$ch = curl_init();
curl_setopt_array($ch, array(
CURLOPT_URL => "https://api.envato.com/v3/market/author/sale?code={$code}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => array(
"Authorization: Bearer {$personalToken}",
"User-Agent: Purchase code verification script"
)
));
$response = @curl_exec($ch);
$responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch) > 0) {
throw new Exception("Failed to connect: " . curl_error($ch));
}
switch ($responseCode) {
case 404: throw new Exception("Invalid purchase code");
case 403: throw new Exception("The personal token is missing the required permission for this script");
case 401: throw new Exception("The personal token is invalid or has been deleted");
}
if ($responseCode !== 200) {
throw new Exception("Got status {$responseCode}, try again shortly");
}
$body = @json_decode($response);
if ($body === false && json_last_error() !== JSON_ERROR_NONE) {
throw new Exception("Error parsing response, try again");
}
return $body;
}
Example usage:
try {
// Pass in the purchase code from the user
$sale = getPurchaseCode("PURCHASE_CODE_HERE");
// Example: Check if the purchase is still supported
$supportDate = strtotime($sale->supported_until);
$supported = $supportDate > time() ? "Yes" : "No";
echo "Item: {$sale->item->name} <br>";
echo "Buyer: {$sale->buyer} <br>";
echo "License: {$sale->license} <br>";
echo "Supported until: {$sale->supported_until} <br>";
echo "Currently supported?: {$supported} <br>";
}
catch (Exception $ex) {
// Print the error so the user knows what's wrong
echo $ex->getMessage();
}
PHP (WordPress)
Here’s the same function as above, but rewritten using wp_remote_get
instead of cURL
. This function accepts the purchase code as its sole argument and returns a parsed object. It will throw an exception if the code is incorrect, or if there was an unexpected issue.
Replace the YOUR_PERSONAL_TOKEN_HERE
on line 2 with your personal token.
Note: Don’t put this code inside your item. Instead, place it on your own server, and have your item communicate with your server instead. This is required to keep your personal token secure – it’s like a password for your account.
// TODO: Return WP_Error objects instead of throwing exceptions
function getPurchaseCode($code) {
$personalToken = "YOUR_PERSONAL_TOKEN_HERE";
// Surrounding whitespace can cause a 404 error, so trim it first
$code = trim($code);
// Make sure the code looks valid before sending it to Envato
// This step is important - requests with incorrect formats can be blocked!
if (!preg_match("/^([a-f0-9]{8})-(([a-f0-9]{4})-){3}([a-f0-9]{12})$/i", $code)) {
throw new Exception("Invalid purchase code");
}
$url = "https://api.envato.com/v3/market/author/sale?code={$code}";
$response = wp_remote_get($url, array(
"headers" => array(
"Authorization" => "Bearer {$personalToken}",
"User-Agent" => "Purchase code verification script"
)
));
if (is_wp_error($response)) {
throw new Exception("Failed to look up purchase code");
}
$responseCode = wp_remote_retrieve_response_code($response);
switch ($responseCode) {
case 404: throw new Exception("Invalid purchase code");
case 403: throw new Exception("The personal token is missing the required permission for this script");
case 401: throw new Exception("The personal token is invalid or has been deleted");
}
if ($responseCode !== 200) {
throw new Exception("Got status {$responseCode}, try again shortly");
}
$body = @json_decode(wp_remote_retrieve_body($response));
if ($body === false && json_last_error() !== JSON_ERROR_NONE) {
throw new Exception("Error parsing response, try again");
}
return $body;
}
Example usage:
try {
// Pass in the purchase code from the user
$sale = getPurchaseCode("PURCHASE_CODE_HERE");
// Example: Check if the purchase is still supported
$supportDate = strtotime($sale->supported_until);
$supported = $supportDate > time() ? "Yes" : "No";
echo "Item: {$sale->item->name} <br>";
echo "Buyer: {$sale->buyer} <br>";
echo "License: {$sale->license} <br>";
echo "Supported until: {$sale->supported_until} <br>";
echo "Currently supported?: {$supported} <br>";
}
catch (Exception $ex) {
// Print the error so the user knows what's wrong
echo $ex->getMessage();
}
Node.js (npm package)
Node.js users can install my unofficial npm package conveniently named envato. It’s fully maintained, up to date, and written in TypeScript. I use it myself for many projects.
Installation:
npm install envato
Example usage:
import { Client } from 'envato';
// Add your personal token
const client = new Client('YOUR_PERSONAL_TOKEN_HERE');
// Example usage
async function getPurchaseCode(code) {
try {
const sale = await client.private.getSale(code);
if (sale !== undefined) {
console.log({
item: sale.item.name,
buyer: sale.buyer,
license: sale.license,
supportedUntil: sale.supported_until,
supportedNow: sale.supported_until > new Date() ? 'Yes' : 'No'
});
}
else {
console.error('Invalid purchase code!');
}
}
catch (error) {
// Your code should only reach this point due to a server error,
// an outage, or an invalid token
console.error('Caught an exception:', error);
}
}
Libraries
Here are some existing libraries and wrappers that you can quickly import into your project. If there’s something missing from this list, feel free to add it. (Please refrain from posting libraries that were last updated before 2017).
PHP (Packagist):
- baileyherbert/envato – Full wrapper for the Envato API
- morningtrain/envato-api – Full wrapper for the Envato API
Node.js (npm)
- envato (unofficial) – A library for the Envato API with fully typed responses
- envato-api-request – A tiny request wrapper for the Envato API
CodeCanyon (Premium libraries)
- Enver – .NET library that comes with sample C# and VB projects
Plugins & scripts
Here are some plugins, scripts, and apps that can take care of purchase code verification for you. If there’s something missing from this list, feel free to add it, but all items must be open-source and free unless approved for sale on Envato Market.
CodeCanyon
- Envato - Purchase Code Verify – Standalone web application (PHP Script)
- EPCV - Envato Purchase Code Verifier – Standalone web application (PHP Script)
- CF7 Envato Market Item Support Request – Add a purchase code field to Contact Form 7 (WP)
- CF7 Purchase Code Checker – Add a purchase code field to Contact Form 7 (WP)
- BBPress Purchase Code Checker – Add a purchase code field to BBPress (WP)
- JValidate – Add a purchase code field to the WordPress registration form (WP)
- Elite Licenser - Manage licenses & auto-updates for WordPress plugins, themes, and scripts (WP)
WordPress.org
- License For Envato – License management system
- EM Purchase Code Validator – Add a purchase code check form on any page
Browser extensions
- Easy Envato (GitHub) – Select and verify a purchase code on any page (Chrome)