Skip to main content

Nillion Storage APIs

The Nillion Storage APIs provide a simple HTTP interface for storing and retrieving secrets on the Nillion Network Testnet with built-in management of store IDs and secret names.

info

The Storage APIs are suitable for quick hackathon projects and proof of concepts. If you need lower-level control or want to handle store ID management yourself, check out our Python Client for backend applications and Javascript Client for frontend applications.

Overview

The Nillion Storage APIs make it easy to quickly bootstrap a hackathon project that securely stores and retrieves secret data from the Nillion Network Testnet. APIs include built-in management of store IDs (locations of your secrets on Nillion) and abstract away Testnet payments. You can use Nillion Storage APIs to:

  • Create an app id
  • Store 2 types of secrets (numbers and strings/blobs)
  • Customize secret permissions: grant retrieve, update, delete, and compute permissions to specific User IDs when storing secrets
  • List all store IDs and names of secrets for your app id
  • Retrieve secret values from Nillion using their store IDs

Storage APIs Quickstart

This guide shows how to store secrets, list all store IDs and secret names for your app, and retrieve secrets using the Nillion Storage APIs.

Prerequisites

All you need is a way to make HTTP requests. The examples below use curl and JavaScript. You can explore and test all API endpoints directly from the Nillion Storage API Reference.

0: Register Your App

First run the following command from your terminal to register a new app:

curl -X POST https://nillion-storage-apis-v0.onrender.com/api/apps/register

This returns an app_id to track the store IDs for your secrets. Save the app_id from the response. This is your app's unique identifier.

1. [Optional] Check Your User ID

Check the deterministic user ID generated by your user seed using POST /api/user. You can share this user ID with others so they can give you permissions to retrieve their secrets.

const USER_SEED = 'user_123'; // generates a deterministic nillion user id; use any string
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';

// 1. Check your deterministic user ID
console.log('Checking user ID generated by your seed...');
const user = await fetch(`${API_BASE}/api/user`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
nillion_seed: USER_SEED,
}),
}).then((res) => res.json());
console.log('Your User ID:', user.nillion_user_id);

2. Store a Secret Number

Store a number secret using POST /api/apps/{app_id}/secrets. The empty permissions arrays mean only the storing user has access.

Make sure to update the APP_ID below with your app_id from step 0 before running the code:

const APP_ID = 'INSERT_YOUR_APP_ID_HERE';
const USER_SEED = 'user_123'; // generates a deterministic nillion user id; use any string
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';

// 2. Store first secret (number)
console.log('\nStoring first secret...');
const storeResult1 = await fetch(`${API_BASE}/api/apps/${APP_ID}/secrets`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: {
nillion_seed: USER_SEED,
secret_value: 16,
secret_name: 'my_secret_number',
},
permissions: {
retrieve: [],
update: [],
delete: [],
compute: {},
},
}),
}).then((res) => res.json());
console.log('First secret stored at:', storeResult1);

3. Store a Secret String

Store a string/blob secret using the same endpoint.

Make sure to update the APP_ID below with your app_id from step 0 before running the code:

const APP_ID = 'INSERT_YOUR_APP_ID_HERE';
const USER_SEED = 'user_123'; // generates a deterministic nillion user id; use any string
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';

// 3. Store second secret (string/blob)
console.log('\nStoring second secret...');
const storeResult2 = await fetch(`${API_BASE}/api/apps/${APP_ID}/secrets`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: {
nillion_seed: USER_SEED,
secret_value: 'gm!',
secret_name: 'my_secret_blob',
},
permissions: {
retrieve: [],
update: [],
delete: [],
compute: {},
},
}),
}).then((res) => res.json());
console.log('Second secret stored at:', storeResult2);

4. List Store IDs

Get all store IDs for your app using GET /api/apps/{app_id}/store_ids to find your secrets.

Make sure to update the APP_ID below with your app_id from step 0 before running the code:

const APP_ID = 'INSERT_YOUR_APP_ID_HERE';
const USER_SEED = 'user_123'; // generates a deterministic nillion user id; use any string
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';

// 4. List store IDs
const storeIds = await fetch(`${API_BASE}/api/apps/${APP_ID}/store_ids`)
.then((res) => res.json())
.then((data) => data.store_ids);
console.log('Store IDs:', storeIds);

5. Retrieve Secrets

Get each secret's value using GET /api/secret/retrieve/{store_id} with the correct secret name and user seed.

Make sure to update the APP_ID below with your app_id from step 0 before running the code:

const APP_ID = 'INSERT_YOUR_APP_ID_HERE';
const USER_SEED = 'user_123'; // generates a deterministic nillion user id; use any string
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';
const storeIds = await fetch(`${API_BASE}/api/apps/${APP_ID}/store_ids`)
.then((res) => res.json())
.then((data) => data.store_ids);

// 5. Retrieve both secrets using the store IDs we just created
console.log('\nRetrieving secrets...');
const secret1 = await fetch(
`${API_BASE}/api/secret/retrieve/${storeIds[0].store_id}?retrieve_as_nillion_user_seed=${USER_SEED}&secret_name=${storeIds[0].secret_name}`
).then((res) => res.json());
console.log('First secret retrieved:', secret1);

const secret2 = await fetch(
`${API_BASE}/api/secret/retrieve/${storeIds[1].store_id}?retrieve_as_nillion_user_seed=${USER_SEED}&secret_name=${storeIds[1].secret_name}`
).then((res) => res.json());
console.log('Second secret retrieved:', secret2);

6. Update Secret

Update an existing secret's value using PUT /api/apps/{app_id}/secrets/{store_id} with the secret's store ID and updated value.

Make sure to update the APP_ID and STORE_ID below with your values before running the code:

const APP_ID = 'INSERT_YOUR_APP_ID_HERE';
const STORE_ID = 'INSERT_YOUR_STORE_ID_HERE'; // use the store_id of the secret you want to update
const USER_SEED = 'user_123'; // generates a deterministic nillion user id; use any string
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';

// Update the secret with a new value
console.log('\nUpdating secret...');
const updateResponse = await fetch(
`${API_BASE}/api/apps/${APP_ID}/secrets/${STORE_ID}`,
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
nillion_seed: USER_SEED,
secret_value: "gm gm gm gm!",
secret_name: "my_secret" // use the original secret name
}),
}
).then((res) => res.json());
console.log('Secret updated:', updateResponse);

// Verify the updated secret
const verifyResponse = await fetch(
`${API_BASE}/api/secret/retrieve/${STORE_ID}?retrieve_as_nillion_user_seed=${USER_SEED}&secret_name=my_secret`
).then((res) => res.json());
console.log('Updated secret retrieved:', verifyResponse);

Quickstart Complete Code

Make sure to update the APP_ID below with your app_id from step 0 before running the code:

const APP_ID = 'INSERT_YOUR_APP_ID_HERE';
const USER_SEED = 'user_123'; // your seed generates a deterministic nillion user id - check it in step 1
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';

async function runQuickstart() {
try {
// 1. Check your deterministic user ID
console.log('Checking user ID generated by your seed...');
const user = await fetch(`${API_BASE}/api/user`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
nillion_seed: USER_SEED,
}),
}).then((res) => res.json());
console.log('Your User ID:', user.nillion_user_id);

// 2. Store first secret (number)
console.log('\nStoring first secret...');
const storeResult1 = await fetch(`${API_BASE}/api/apps/${APP_ID}/secrets`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: {
nillion_seed: USER_SEED,
secret_value: 16,
secret_name: 'my_secret_number',
},
permissions: {
retrieve: [],
update: [],
delete: [],
compute: {},
},
}),
}).then((res) => res.json());
console.log('First secret stored at:', storeResult1);

// 3. Store second secret (string/blob)
console.log('\nStoring second secret...');
const storeResult2 = await fetch(`${API_BASE}/api/apps/${APP_ID}/secrets`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: {
nillion_seed: USER_SEED,
secret_value: 'gm!',
secret_name: 'my_secret_blob',
},
permissions: {
retrieve: [],
update: [],
delete: [],
compute: {},
},
}),
}).then((res) => res.json());
console.log('Second secret stored at:', storeResult2);

// 4. List store IDs
console.log('\nListing store IDs...');
const storeIds = await fetch(`${API_BASE}/api/apps/${APP_ID}/store_ids`)
.then((res) => res.json())
.then((data) => data.store_ids);
console.log('Store IDs:', storeIds);

// 5. Retrieve both secrets using the store IDs we just created
console.log('\nRetrieving secrets...');
const secret1 = await fetch(
`${API_BASE}/api/secret/retrieve/${storeIds[0].store_id}?retrieve_as_nillion_user_seed=${USER_SEED}&secret_name=${storeIds[0].secret_name}`
).then((res) => res.json());
console.log('First secret retrieved:', secret1);

const secret2 = await fetch(
`${API_BASE}/api/secret/retrieve/${storeIds[1].store_id}?retrieve_as_nillion_user_seed=${USER_SEED}&secret_name=${storeIds[1].secret_name}`
).then((res) => res.json());
console.log('Second secret retrieved:', secret2);

// 6. Update first secret
console.log('\nUpdating first secret...');
const updateResponse = await fetch(
`${API_BASE}/api/apps/${APP_ID}/secrets/${storeIds[0].store_id}`,
{
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
nillion_seed: USER_SEED,
secret_value: "gm gm gm gm!",
secret_name: storeIds[0].secret_name
}),
}
).then((res) => res.json());
console.log('Secret updated:', updateResponse);

// Verify the update
const verifyUpdate = await fetch(
`${API_BASE}/api/secret/retrieve/${storeIds[0].store_id}?retrieve_as_nillion_user_seed=${USER_SEED}&secret_name=${storeIds[0].secret_name}`
).then((res) => res.json());
console.log('Updated secret retrieved:', verifyUpdate);

} catch (error) {
console.error('Error in flow:', error);
}
}

// Run the quickstart
runQuickstart();

How to Share Secrets with Other Users

Store with Permissions

To give another user access to your secrets, include their user_id in the permissions arrays when storing.

Make sure to update the APP_ID below with your app_id from step 0 before running the code:

const APP_ID = 'INSERT_YOUR_APP_ID_HERE';
const USER_SEED = 'user_123'; // generates a deterministic nillion user id; use any string
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';

// Example using a "test" user seed - your friend should use their own unique seed in production
const friend_user_id =
'63P5NjU6a2zkjJqengfuDuwMUF9Yu3ogrrqMPNjidc4ogfcvefDchZgRNNJQg9T3WKiyZ4L7kF4zGwFurpxCo5bP';

const storeResultForFriend = await fetch(
`${API_BASE}/api/apps/${APP_ID}/secrets`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
secret: {
nillion_seed: USER_SEED,
secret_value: 'secret message to my friend!',
secret_name: 'message_to_friend',
},
permissions: {
retrieve: [friend_user_id], // give friend retrieve permission
update: [],
delete: [],
compute: {},
},
}),
}
).then((res) => res.json());
console.log('Secret stored for friend:', storeResultForFriend);

Retrieve with Permissions

If you tell your friend the store id, that friend can then retrieve the secret using their seed:

Make sure to update the store_id below before running the code:

const store_id = 'store_id_from_above';
const API_BASE = 'https://nillion-storage-apis-v0.onrender.com';
const friend_user_seed = 'test'; // friends should use their own unique seed

const secret = await fetch(
`${API_BASE}/api/secret/retrieve/${store_id}?retrieve_as_nillion_user_seed=${friend_user_seed}&secret_name=message_to_friend`
).then((res) => res.json());
console.log('Secret retrieved by friend:', secret);