🔒Unlockables

Attach exclusive content to your NFTs, only accessible by holders

Unlockables are secret files or data which can only be access by holders of your NFT. You can use unlockables to include HD versions of artwork, source files, 3D models or any other digital download with the purchase of your NFT.

You can even include dynamic data with Webhook unlockables, which send a copy of the results to your API for custom processing, before returning the response in the verification results. This can be used to return different files depending on the number of tokens a user has or token traits, or to perform an additional action like subscribing the user to a holders-only mailing list.

You don't need to make any changes to your smart contract, and unlockables can be added to existing contracts which have already been deployed.

Unlockable types

There are three main types of unlockables:

  • Files (images, videos or digital downloads)

  • JSON or Plain Text

  • Webhooks (dynamic content)

You can create as many unlockables as you like, and request specific (or all) be returned in verification results. For more information on using unlockables with the Browser SDK, check out the SDK usage.

Files

Before creating your unlockable, you need to upload the file to some publicly accessible location. All requests are proxied through the Verify API, so this location won't be revealed to end users.

You can upload these files anywhere, but we recommend using S3 or similar object storage, with a randomized filename or hash to prevent the URL being easily guessed. You should not link to this location from your website or any publicly accessible content, as it would reveal the origin URL which could be accessed without authentication.

We also support IPFS URLs (using the ipfs:// protocol) which will be automatically proxied without revealing the CID to end users

For maximum security you can set firewall rules to disable access except from the Diamond Network servers by whitelisting the following IP addresses: 164.90.244.244.

Once uploaded create an unlockable via the Dashboard or API (details below) and request an access token during Verify requests (see Browser SDK Usage).

JSON & Plain Text

To return arbitrary JSON or plain text, create an unlockable as described below and provide a static JSON object or text to return. This is useful for revealing store discount codes, secret URLs and other data which doesn't need to change depending on the verification results.

Webhooks

Webhook unlockables are the most flexible, but require you to implement an API endpoint to process the request and generate a response.

Webhook unlockables are executed for every request, regardless of whether it was successful. This allows you to revoke access if a previously verified user no longer has your NFT, but you cannot assume all attempts are verified as holders.

You should always validate the signed JWT in webhook requests to ensure the request hasn't been forged

On a verification request, your endpoint will receive a POST request with a JSON body in the same format as the results object from the Browser SDK. Your application can perform additional processing and filtering before returning a response which will then be returned to the user.

You can preview and test webhook unlockables using RequestBin

Requirements

  • Must return a 2XX status code

  • Must return a Content-Type header of:

    • application/json

    • text/html

    • text/plain

  • Must return a response within 10 seconds or the request will timeout

If you'd like to return dynamic files from a webhook unlockable, we recommend uploading your files to a private S3 bucket (or similar object storage) and return signed URLs to grant temporary access (this is similar to how native file unlockables work).

Send extra data to webhooks

You can include arbitrary data in verification requests, which will be passed to Webhook unlockables. This is useful for linking requests to a user ID in your system, or passing additional data like an email address to the webhook handler.

Data must be encoded as a string, with a maximum length of 512 characters.

verify.nft({
  // ... Chain and contract settings
  data: {
    value: "[email protected]",
    // Or you can include an object by serializing it
    // value: "{\"id\":\"snekspr\"}"
  }
})

This data will be included in the verification results under result.data.value

{
  "id": "894bdc90-b156-4535-9711-665019d47414",
  "result": {
    "at": "2022-03-28T14:53:11.661Z",
    "ownership": true,
    "wallet": {
      "address": "sneksprLoHxxRAyLS9W4oZibXRJX9Q69m1Bnv2hRCAE",
      "verified": true
    },
    "data": {
      "value": "[email protected]",
      "verified": false
    }
},

Hold up: did you spot the issue? The data value is provided on the frontend, so the user could tamper with it (for example, change it to a friends email to get them subscribed)

Securing data passed to webhooks

There is an additional parameter you can pass:hmac. The HMAC is a hash of your secret API key and the data value. When a HMAC is provided, we automatically verify it and reject the request if it's invalid. You don't need to provide one, but we highly recommend it if you need to securely connect verification requests to existing user identities.

You should use a HMAC whenever your webhook needs to be sure the data passed hasn't been tampered with

Here is an example for generating a HMAC on Node.js:

const crypto = require("crypto")

const data = "[email protected]"
const key = "sk_XXXXXXXX"

// 98fb6ba9634e2922b6026f6d896e222561e672f14913d81b9f01ebb511e39d36
crypto.createHmac("sha1", key)
  .update(data)
  .digest("hex")

We then pass this HMAC to the request along with the the data:

verify.nft({
  // ... Chain and contract settings
  data: {
    value: "[email protected]",
    hmac: "98fb6ba9634e2922b6026f6d896e222561e672f14913d81b9f01ebb511e39d36"
  }
})

Or if you're using PHP (including Wordpress) you can generate the HMAC in one short line:

verify.nft({
  // ... Chain and contract settings
  data: {
    value: "[email protected]",
    hmac: "<?php echo hash_hmac('sha256', '[email protected]', 'sk_XXXXXXXX') ?>"
  }
})

The Verify API will check the provided HMAC, and reject the request if the data has been changed in any way since the HMAC was generated.

In the results the data will be provided, but now verified = true and can be trusted.

{
  "id": "894bdc90-b156-4535-9711-665019d47414",
  "result": {
    "at": "2022-03-28T14:53:11.661Z",
    "ownership": true,
    "wallet": {
      "address": "sneksprLoHxxRAyLS9W4oZibXRJX9Q69m1Bnv2hRCAE",
      "verified": true
    },
    "data": {
      "value": "[email protected]",
      "verified": true
    }
},

Create an unlockable

Via the Dashboard

Create a new app by clicking "Create App", or select an existing app.

Click the "Create" button next to the "Unlockables" header, and enter the settings for your unlockable.

Via the API

For details on creating unlockables through the API, please refer to the API documentation:

👨‍💻pageREST API

Accessing unlockables

Users are granted access to unlockables by completing a verification request, either via the Browser SDK or a custom UI. You can control the unlockables returned by providing an array of unlockable names under the unlockables parameter:

pageBrowser SDK

You can also grant access to unlockables manually by creating a pre-signed URL on your server. Check out the "Fetch unlockable content" docs on the REST API for details:

👨‍💻pageREST API

Last updated