Capture
Search
K

Initial Asset Registration

Before Starting

There are three major methods for turning your digital media files into Captures, registering them as Web3 assets, and accessing the Capture ecosystem. These methods include:
  1. 1.
    Using the Capture Cam
  2. 2.
    Using the Capture Dashboard
  3. 3.
    Registering with the Capture API
This page will primarily focus on the third method, registration with the API.

Register Captures

Registering assets via API is a simple way to create Captures. You will need to acquire your Capture Token before uploading the file. If you do not already have a Capture Token yet, please follow the instruction provided to create one.
The API key is optional. If you possess an API key, it's advisable to include it in the header as it helps in recording the name of the service where the asset was registered.
The Capture API is a pay-as-you-go system, which means you only pay for the API calls you make. This is a cost-effective way to use the API and it allows you to control your expenses. Make sure to top up and ensure sufficient funds in your wallet in the form of Credits or NUM to cover the cost. Payment for services is processed using NUM; if you want to know how much it costs in USD, you can check CoinGecko or CoinMarketCap.
post
https://api.numbersprotocol.io/api/v3/assets/
Register asset
Example
Response
curl -s -X POST 'https://api.numbersprotocol.io/api/v3/assets/' \
-H "Authorization: token YOUR_CAPTURE_TOKEN" \
-F 'asset_file=@/tmp/demo.jpg' \
-F 'meta={
"proof": {
"hash": "",
"mimeType": "",
"timestamp": ""
},
"information": [
{
"provider": "Capture API",
"name": "version",
"value": "v3"
}
]
}' \
-F 'caption=This is an example caption.' \
-F 'headline=This is an example headline.'
{
"id": "bafybeie23hdjuurtc5n77vbhjx6mmrmjo3lyzmtks4eki5ibwpqjoeb3eq",
"asset_file_name": "demo.jpg",
"asset_file_mime_type": "image/jpeg",
"caption": "This is an example caption.",
"headline": "This is an example headline.",
}
Please note that proof session is a required part of your metadata. The hash, mimeType, and timestamp fields may be left empty, as the Capture backend will automatically calculate these values for you, as shown in the example above.
However, the more information you provide, the more trustworthy your assets are, which also make them more "decentralized". The example of meta can be found here.
It's preferable to provide an image file when the asset file is not an image. For more information on how this registration API works, please refer to the API documentation.

Adding Signatures

To safeguard asset integrity in the Capture system, Capture employs client-side digital signatures based on Ethereum's EIP-191 standard. This approach guarantees that asset metadata remains in a verifiable and secure state. When you're registering an asset, enhancing its authenticity can be achieved by including two optional JSON string fields: signed_metadata and signature. Here’s how they work:
Details on signed_metadata
The signed_metadata field is essential for storing the metadata poised for signing. For specifics on what this metadata entails and guidance on generating it, do take a look at our IntegrityCid page.
The Structure of signature
The signature field should contain the actual digital signature. An example format is as follows:
[
{
"proofHash": "78b67e15077577a9b25393f13bfccde3f94f990cf2a7bb0584a51f09196abbbf",
"provider": "ExampleCaptureSignatureProvider",
"signature": "0xf64d0ea52564dd442bbea7f212dbf2fe464fd5674ffd9b68593b3e757c14873c5136afb4394aa5b4ef529ecb693aae84f827af1ce8ddb7538d46432022f8d1771c",
"publicKey": "0x114e5E0dce98180c98ADC62E9Ac6Ea7184417ecd",
"integritySha": "78e11c61f90ba0c52e9f10e4d829c09e1a0aeffbcf77ae940836c494cdb5ac8b"
}
]
Field Name
Description
proofHash
The sha256sum of the asset.
provider
Signature provider's name.
signature
The signature generated by EIP-191 standard.
publicKey
The Ethereum wallet address used for signing.
integritySha
The sha256sum of signed_metadata.
By opting to include these fields, you're adding an extra layer of security to your asset registration process, reinforcing the trustworthiness of each asset within the Capture system.
You may generate signature using the example JavaScript code below. You will need to install the required package by using command npm i ethers @numbersprotocol/nit.
import crypto from "crypto";
import { promises as fs } from "fs";
import * as nit from "@numbersprotocol/nit";
import { ethers } from "ethers";
async function calculateSHA256(file) {
const data = await fs.readFile(file);
const hash = crypto.createHash("sha256");
hash.update(data);
return hash.digest("hex");
}
async function generateIntegritySha(proofMetadata) {
// Create a JSON string of the proofMetadata
const data = JSON.stringify(proofMetadata, null, 2);
// Calculate its SHA-256 hash using getIntegrityHash
const dataBytes = ethers.toUtf8Bytes(data);
const integritySha = await nit.getIntegrityHash(dataBytes);
return integritySha;
}
async function main() {
const filename = "<your-asset-file-name>"; // Replace with your filename
const privateKey = "<your-private-key>"; // Replace with your private key
const proofHash = await calculateSHA256(filename);
const unixTimestamp = Math.floor(Date.now() / 1000);
const proofMetadata = {
asset_mime_type: "image/png",
caption: "",
created_at: unixTimestamp,
proof_hash: proofHash,
recorder: "Capture",
spec_version: "2.0.0",
};
const signMessage = JSON.stringify(proofMetadata, null, 2);
console.log("signed_metadataJSON", signMessage);
// Generate the integrity SHA from the proofMetadata
const integritySha = await generateIntegritySha(proofMetadata);
// Sign the integrity SHA
const signer = new ethers.Wallet(privateKey);
const publicKey = await signer.getAddress();
const signature = await nit.signIntegrityHash(integritySha, signer);
const signatureJSON = JSON.stringify({
proofHash,
provider: "ExampleCaptureSignatureProvider",
signature,
publicKey,
integritySha,
});
console.log('signatureJSON', signatureJSON);
}
main();
For implementation details of nit.getIntegrityHash and nit.signIntegrityHash used in the signature generation process, visit Github Repository of the open-sourced "Git for Web3 assets" tool Nit for details. The implementation of the above functions can be found at the page.

Verifying signatures

To verify signature, obtain the signed_metadata and signature created in previous step locally or fetch the data following the steps in Query Assets section.
import * as nit from "@numbersprotocol/nit";
import { ethers } from "ethers";
async function verifySignature(signedMetadataJSON, signatureJSON) {
const signatureObject = JSON.parse(signatureJSON);
const integritySha = await nit.getIntegrityHash(
ethers.toUtf8Bytes(signedMetadataJSON)
);
if (integritySha === signatureObject.integritySha) {
console.log("integritySha is correct!");
} else {
console.log("integritySha is incorrect.");
}
const recoveredAddress = await nit.verifyIntegrityHash(
signatureObject.integritySha,
signatureObject.signature
);
if (recoveredAddress === signatureObject.publicKey) {
console.log("Signature is valid!");
} else {
console.log("Signature is invalid.");
}
}
// Replace these value with your actual signed_metadata and signature
const signedMetadataJSON = `{
"asset_mime_type": "image/png",
"caption": "",
"created_at": 1701688997,
"proof_hash": "01b0d72b491486379e9657eaf960e1ab114fbe6479a757fdaf2144dc9d654d58",
"recorder": "Capture",
"spec_version": "2.0.0"
}`;
const signatureJSON =
'{"proofHash":"01b0d72b491486379e9657eaf960e1ab114fbe6479a757fdaf2144dc9d654d58","provider":"ExampleCaptureSignatureProvider","signature":"0xa6615b4a6a563eaf89e000c6f7b46bcb3f4fabb90438cc44e46c9ff282e4ef857352735e051637f2737d7d30d8f8a3dd9d048b102413751ac06a96376042e3061b","publicKey":"0x114e5E0dce98180c98ADC62E9Ac6Ea7184417ecd","integritySha":"39c8352f98872ce41fc79c2446f2fa6903fa68f73d6b2cb99f843844e5e01291"}';
verifySignature(signedMetadataJSON, signatureJSON);
The implementation detail of nit.verifyIntegrityHash can also be found on the Nit Github Repository page.

Additional Capture Information

Additional information in Capture is important because it helps to build trust and transparency in the digital media assets that are created and stored on the decentralized web. Having detailed information about an asset, such as its creation date, location, and owner, is crucial for establishing its authenticity and provenance. More verifiable information, more provenance of your Captures.
Adding information to a Capture is straightforward, one just needs to extend the information blocks during the asset registration. Information blocks can be defined as follows:
{
"provider": "InfoSnapshot",
"name": "Current GPS Latitude",
"value": 25.049190
},
The provider field refers to the source of the information block, while the name field represents the name of the information block. The value to be registered should be placed in the value field. This allows for clear and organized storage of information about the Capture.
The following shows some pre-defined information blocks:
Provider
Name
Sample Value
InfoSnapshot
creationGPSAddress
No. 299, Section 4, Bade Road, Songshan District Taipei City
InfoSnapshot
Timestamp
2021-04-23T02:30:00.279Z
InfoSnapshot
creationGPSLatitude
25.049190
InfoSnapshot
creationGPSLongitude
121.566440
InfoSnapshot
Device Build Tags
android
InfoSnapshot
GPSVerticalAccuracy
8.0
Exif
GPSAltitude
-4.617279052734375
Exif
GPSBearing
212.94905
Exif
GPSverticalAccuracyMeters
8.0
Exif
GPSLongitude
121,31,50.861E
Exif
GPSLatitude
25,2,42.842N
Android
Manufacturer
Samsung
Android
DeviceName
Samsung Galaxy Fold 4
Sensor
Accelerometer
SensorData(accuracy=3.0, value=[-2.2584498, 5.544669, 7.7695217])
Sensor
GameRotationVector
SensorData(accuracy=3.0, value=[0.28894028, 0.089926116, -0.077565834, 0.94995135])
Sensor
Gravity
SensorData(accuracy=NO_UPDATE_RECEIVED_DURING_SNAP, value=[-2.1173487, 5.2436786, 8.011802])
Sensor
Gyroscope
SensorData(accuracy=3.0, value=[0.0090546375, 0.0026631376, 0.011718297])
PGP
Public Key
----BEGIN PGP PUBLIC KEY BLOCK-----Version: BCPG v@RELEASE_NAME@mQINBF5emRQBEAC0YLMyonrxA==YeTD-----END PGP PUBLIC KEY BLOCK-----
IPFS
Nid
bafybeie23hdjuurtc5n77vbhjx6mmrmjo3lyzmtks4eki5ibwpqjoeb3eq

Signature verification

Verifying a signature is crucial for ensuring the authenticity and integrity of data. Signatures are used to confirm that data or assets have not been tampered with and originate from a trusted source. In this guide, we'll walk through the process of verifying a signature. After registering a capture with Capture Cam or Capture Dashboard, you can verify the asset signature by calling the "verify signature" endpoint. To call the "verify signature" endpoint, you will need two pieces of information:
  1. 1.
    CID: Asset id which can obtain from the response received after registering the capture.
  2. 2.
    PUBLIC KEY: This should be the same public key used when adding signatures.
Oops, something is missing.We could not find the original source to display this content.
Example
Response: Signature verified
Response: Signature not verified
curl -s -X GET 'https://api.numbersprotocol.io/api/v3/assets/{YOU_CID}/verify-signature/?address={YOUR_PUBLIC_KEY}' \
-H "Authorization: token YOUR_CAPTURE_TOKEN" \
-H "Accept: application/json"
{
"signed_actions": {
"action": "mint",
"method": "POST",
"signed_url": "https://api.numbersprotocol.io/api/v3/assets/{YOUR_CID}/mint/?signature=None",
"expired_at": null
}
}
{
"error": {
"type": "signature_verification_failed",
"message": "The address recovered from the signature and message is different with the provided address.",
"details": {
"provided_address": "{YOUR_PUBLIC_KEY}"
}
},
"status_code": 400
}
If the signature is valid, you will receive a '200 OK' similar to Response: Signature verified. However, if the signature is not valid, the response will be in the '40X' range similar to Response: Signature not verified, indicating an error.

Import Assets

The importing API endpoint is used for importing NFTs.
post
https://api.numbersprotocol.io/api/v3
/assets/import/
Import asset
Example: import an NFT where the owner is the asset wallet
Example: import an NFT where the owner is not the asset wallet
Response
curl -s -X POST 'https://api.numbersprotocol.io/api/v3/assets/import/' \
-H "Authorization: token YOUR_CAPTURE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"nft": {
"nft_chain_id": 1,
"nft_contract_address": "0xfDD0642479Bb1E219945E7a44B882AfaB8BaF68B",
"nft_token_id": "1"
},
"meta": "{\"proof\": {\"hash\": \"\",\"mimeType\":\"\",\"timestamp\": \"\"},\"information\": [{\"provider\": \"Capture API\",\"name\": \"version\",\"value\": \"v3\"}]}"
}'
curl -s -X POST 'https://api.numbersprotocol.io/api/v3/assets/import/' \
-H "Authorization: token YOUR_CAPTURE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"nft": {
"nft_chain_id": 1,
"nft_contract_address": "0xfDD0642479Bb1E219945E7a44B882AfaB8BaF68B",
"nft_token_id": "1"
},
"meta": "{\"proof\": {\"hash\": \"\",\"mimeType\":\"\",\"timestamp\": \"\"},\"information\": [{\"provider\": \"Capture API\",\"name\": \"version\",\"value\": \"v3\"}]}",
"signed_metadata": "{\"api_version\": \"v3\"}",
"signature": "[{\"proofHash\": \"78b67e15077577a9b25393f13bfccde3f94f990cf2a7bb0584a51f09196abbbf\",\"provider\": \"Web3\",\"signature\": \"0x75f92194df339799748ad8bd12ad4b45ad7b6590431b67900c3b8df21764892b58cbcafb743253e5f70a7965e3706f3d556a056a0089cb164fa2b0fa5cf37ad91c\",\"publicKey\": \"0xbAbaB9E7790202A1a4d171E44767A531C25e200C\"}]"
}'
{
"id": "bafybeie23hdjuurtc5n77vbhjx6mmrmjo3lyzmtks4eki5ibwpqjoeb3eq",
"asset_file_name": "imported.jpg",
"asset_file_mime_type": "image/jpeg",
"caption": "This is an example.",
"nft_token_id": "1",
"nft_chain_id": 1,
"nft_contract_address": "0xfDD0642479Bb1E219945E7a44B882AfaB8BaF68B"
}
Example: Import an NFT with an associated image
Response
curl -s -X POST 'https://api.numbersprotocol.io/api/v3/assets/import/' \
-H "Authorization: token YOUR_CAPTURE_TOKEN" \
-F 'nft.nft_chain_id=1' \
-F 'nft.nft_contract_address=0xfDD0642479Bb1E219945E7a44B882AfaB8BaF68B' \
-F 'nft.nft_token_id=2' \
-F 'image_file=@/tmp/demo.jpg' \
-F 'signed_metadata={"api_version": "v3"}' \
-F 'signature=[{
"proofHash": "78b67e15077577a9b25393f13bfccde3f94f990cf2a7bb0584a51f09196abbbf",
"provider": "Web3",
"signature": "0x75f92194df339799748ad8bd12ad4b45ad7b6590431b67900c3b8df21764892b58cbcafb743253e5f70a7965e3706f3d556a056a0089cb164fa2b0fa5cf37ad91c",
"publicKey": "0xbAbaB9E7790202A1a4d171E44767A531C25e200C"
}]' \
-F 'meta={
"proof": {
"hash": "",
"mimeType": "",
"timestamp": ""
},
"information": [
{
"provider": "Capture API",
"name": "version",
"value": "v3"
}
]
}'
{
"id": "bafybeiagc3fjrdrrookzkbrtdnfuulpfmeqej3bqc6wpmuttsclykuidt4",
"asset_file_name": "imported.mp4",
"asset_file_mime_type": "video/mp4",
"image_file_mime_type": "image/jpeg",
"caption": "This is an example.",
"nft_token_id": "2",
"nft_chain_id": 1,
"nft_contract_address": "0xfDD0642479Bb1E219945E7a44B882AfaB8BaF68B"
}
The nft is required to import an NFT from Numbers Search Engine.
If the NFT owner is not the user's asset wallet, the signed_metadata and signature are also necessary. These will be used to validate the address that signed the signed_metadata as the NFT owner.
It is recommended to provide an image_file when the NFT's image is not in image file format.
If the owner of the imported NFT is the user's asset wallet, the user can perform any NFT operation, including forcing a re-mint of an asset, exporting an asset, creating a transaction, creating an asset-origin product, creating an asset-clone product, or creating pack products from a series. However, if the owner is not the user's asset wallet, the user can only mint new NFTs (create child assets), which includes creating an asset-clone product, and creating pack products from a series.

Query Assets

The following API endpoint can be used to query asset information.
get
https://api.numbersprotocol.io/api/v3/assets/
Query registered assets information
Example: query all assets
Response
curl -s -X GET 'https://api.numbersprotocol.io/api/v3/assets/' \
-H "Authorization: token YOUR_CAPTURE_TOKEN"
[
{
"id": "bafybeie23hdjuurtc5n77vbhjx6mmrmjo3lyzmtks4eki5ibwpqjoeb3eq",
"asset_file_name": "demo.jpg",
"asset_file_mime_type": "image/jpeg",
"caption": "This is an example."
}
]
Example: query one asset
Response
curl -s -X GET 'https://api.numbersprotocol.io/api/v3/assets/YOUR_ASSET_NID/' \
-H "Authorization: token YOUR_CAPTURE_TOKEN"
{
"id": "bafybeie23hdjuurtc5n77vbhjx6mmrmjo3lyzmtks4eki5ibwpqjoeb3eq",
"asset_file_name": "demo.jpg",
"asset_file_mime_type": "image/jpeg",
"caption": "This is an example."
}