PRIV ProtocolPRIV Docs
API Reference

Wallet Marketplace API

Buy and sell data wallet contents on the PRIV Protocol marketplace.

The Wallet Marketplace allows users to sell their approved contributions and purchase data from other users. All transactions are conducted in PRIV tokens.

Browse Listings

GET/api/v1/marketplace/wallet/listings

Browse available data wallet listings. Supports anonymous browsing with optional authentication.

Query Parameters

ParameterTypeRequiredDescription
categorystringNoFilter by category: photo, video, voice, text, mixed
minPricenumberNoMinimum price in PRIV
maxPricenumberNoMaximum price in PRIV
sortstringNoSort order (see below)
pagenumberNoPage number (default: 1)
limitnumberNoResults per page (default: 20, max: 100)

Sort Options

ValueDescription
newestMost recently created (default)
oldestOldest first
price_lowLowest price first
price_highHighest price first
most_salesMost purchases first
highest_ratedHighest rated first

Response

{
  "success": true,
  "data": {
    "listings": [
      {
        "id": "listing_abc123",
        "title": "Nature Photography Collection",
        "description": "50 high-quality nature photos suitable for AI training",
        "category": "photo",
        "tags": ["nature", "outdoor", "landscape"],
        "price_priv": 25.00,
        "status": "active",
        "contribution_count": 50,
        "total_file_size_bytes": 125000000,
        "preview_samples": [
          {
            "contribution_type": "photo",
            "preview_url": "/api/v1/contributions/contrib_xyz/preview",
            "metadata_preview": {}
          }
        ],
        "seller": {
          "id": "usr_seller123",
          "display_name": "DataProvider_a7x2",
          "rating": 4.8,
          "total_sales": 15,
          "member_since": "2023-06-01T00:00:00Z",
          "verified": true
        },
        "total_sales": 12,
        "average_rating": 4.7,
        "created_at": "2024-01-10T10:00:00Z",
        "updated_at": "2024-01-15T12:00:00Z"
      }
    ],
    "pagination": {
      "total": 150,
      "page": 1,
      "limit": 20,
      "total_pages": 8
    }
  }
}

Example: Browse with Filters

curl "https://api.priv.io/v1/marketplace/wallet/listings?category=photo&maxPrice=50&sort=highest_rated" \
  -H "Authorization: Bearer pk_live_xxx"

Create Listing

POST/api/v1/marketplace/wallet/listings

Create a new listing from your approved contributions. Requires authentication.

Request Body

{
  "title": "Nature Photography Collection",
  "description": "50 high-quality nature photos suitable for AI training. Includes outdoor landscapes, wildlife, and botanical images.",
  "category": "photo",
  "tags": ["nature", "outdoor", "landscape", "wildlife"],
  "price_priv": 25.00,
  "contribution_ids": [
    "contrib_abc123",
    "contrib_def456",
    "contrib_ghi789"
  ]
}

Request Fields

FieldTypeRequiredDescription
titlestringYesListing title (max 100 chars)
descriptionstringYesDetailed description (max 2000 chars)
categorystringYesCategory: photo, video, voice, text, mixed
tagsstring[]NoTags for discoverability (max 10)
price_privnumberYesPrice in PRIV tokens
contribution_idsstring[]YesArray of contribution UUIDs to include

All contributions must be approved and have commercial consent enabled.

Response

{
  "success": true,
  "data": {
    "listing_id": "listing_abc123",
    "status": "draft",
    "contribution_count": 50,
    "preview_generated": true,
    "message": "Listing created as draft. Update status to pending_review when ready to publish."
  }
}

Listing Status Flow

draft -> pending_review -> active
                       -> rejected
active -> paused -> active
       -> delisted

Example

curl -X POST "https://api.priv.io/v1/marketplace/wallet/listings" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Nature Photography Collection",
    "description": "50 high-quality nature photos",
    "category": "photo",
    "price_priv": 25.00,
    "contribution_ids": ["contrib_abc123", "contrib_def456"]
  }'

Get Listing Details

GET/api/v1/marketplace/wallet/listings/:id

Get detailed information about a specific listing.

Path Parameters

ParameterTypeRequiredDescription
idstringYesListing UUID

Response

{
  "success": true,
  "data": {
    "listing": {
      "id": "listing_abc123",
      "title": "Nature Photography Collection",
      "description": "50 high-quality nature photos suitable for AI training",
      "category": "photo",
      "tags": ["nature", "outdoor"],
      "price_priv": 25.00,
      "status": "active",
      "contribution_count": 50,
      "total_file_size_bytes": 125000000,
      "preview_samples": [...],
      "seller": {...},
      "total_sales": 12,
      "average_rating": 4.7,
      "sample_cids": ["Qm...", "Qm..."],
      "contribution_types_breakdown": {
        "photo": 50
      },
      "consent_info": {
        "ai_training": true,
        "research": true,
        "commercial": true
      },
      "created_at": "2024-01-10T10:00:00Z",
      "updated_at": "2024-01-15T12:00:00Z"
    },
    "is_owner": false,
    "already_purchased": false
  }
}

Update Listing

PUT/api/v1/marketplace/wallet/listings/:id

Update a listing you own. Only certain fields can be updated based on status.

Request Body

{
  "title": "Updated Title",
  "description": "Updated description",
  "price_priv": 30.00,
  "status": "pending_review",
  "tags": ["nature", "outdoor", "new-tag"]
}

Updatable Fields

FieldCan Update When
titledraft, paused
descriptiondraft, paused
price_privdraft, paused, active
tagsdraft, paused
statusFollows status flow

Valid Status Transitions

FromTo
draftpending_review
pending_reviewactive, rejected (system only)
activepaused, delisted
pausedactive, delisted

Response

{
  "success": true,
  "data": {
    "listing_id": "listing_abc123",
    "status": "pending_review",
    "updated_fields": ["title", "status"],
    "message": "Listing submitted for review. It will be published once approved."
  }
}

Purchase Listing

POST/api/v1/marketplace/wallet/listings/:id/purchase

Purchase access to a listing. Deducts PRIV from buyer and credits seller.

Path Parameters

ParameterTypeRequiredDescription
idstringYesListing UUID to purchase

Request Body (Optional)

{
  "access_duration_days": 30
}

Request Fields

FieldTypeRequiredDescription
access_duration_daysnumberNoAccess duration (default: 30, max: 365)

Response

{
  "success": true,
  "data": {
    "purchase_id": "purchase_xyz789",
    "listing_id": "listing_abc123",
    "access_token": "at_abc123def456...",
    "amount_paid_priv": 25.00,
    "expires_at": "2024-02-15T10:30:00Z",
    "download_count": 0,
    "max_downloads": 10,
    "message": "Purchase successful. Use the access token to download the data."
  }
}

Response Fields

FieldTypeDescription
purchase_idstringUnique purchase identifier
access_tokenstringToken required for downloads
amount_paid_privnumberPRIV amount paid
expires_atstringAccess expiration timestamp
download_countnumberCurrent download count
max_downloadsnumberMaximum allowed downloads

A 5% platform fee is deducted from the sale price. Sellers receive 95% of the listing price.

Example

curl -X POST "https://api.priv.io/v1/marketplace/wallet/listings/listing_abc123/purchase" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
  -H "Content-Type: application/json" \
  -d '{"access_duration_days": 60}'

List Purchases

GET/api/v1/marketplace/wallet/purchases

List your purchases as a buyer.

Query Parameters

ParameterTypeRequiredDescription
pagenumberNoPage number (default: 1)
limitnumberNoResults per page (default: 20, max: 100)

Response

{
  "success": true,
  "data": {
    "purchases": [
      {
        "id": "purchase_xyz789",
        "listing_id": "listing_abc123",
        "listing_title": "Nature Photography Collection",
        "listing_category": "photo",
        "seller_display_name": "DataProvider_a7x2",
        "amount_paid_priv": 25.00,
        "access_token": "at_abc123...",
        "purchased_at": "2024-01-15T10:30:00Z",
        "expires_at": "2024-02-15T10:30:00Z",
        "download_count": 2,
        "max_downloads": 10,
        "status": "active"
      }
    ],
    "pagination": {
      "total": 5,
      "page": 1,
      "limit": 20,
      "total_pages": 1
    }
  }
}

Purchase Status

StatusDescription
activeAccess is valid
expiredAccess has expired
revokedAccess was revoked (refund, etc.)

Download Purchase

GET/api/v1/marketplace/wallet/purchases/:id/download

Get download URLs for a purchased listing.

Path Parameters

ParameterTypeRequiredDescription
idstringYesPurchase UUID

Query Parameters / Headers

Provide the access token via query parameter or header:

MethodParameter
Query?access_token=at_abc123...
HeaderX-Access-Token: at_abc123...

Response

{
  "success": true,
  "data": {
    "purchase_id": "purchase_xyz789",
    "listing_id": "listing_abc123",
    "download_count": 3,
    "max_downloads": 10,
    "downloads": [
      {
        "contribution_id": "contrib_abc123",
        "contribution_type": "photo",
        "filename": "nature_001.jpg",
        "file_size_bytes": 2500000,
        "mime_type": "image/jpeg",
        "gateway_url": "https://gateway.pinata.cloud/ipfs/QmXyz...",
        "cid": "QmXyz..."
      },
      {
        "contribution_id": "contrib_def456",
        "contribution_type": "photo",
        "filename": "nature_002.jpg",
        "file_size_bytes": 3200000,
        "mime_type": "image/jpeg",
        "gateway_url": "https://gateway.pinata.cloud/ipfs/QmAbc...",
        "cid": "QmAbc..."
      }
    ],
    "expires_at": "2024-02-15T10:30:00Z",
    "message": "Download 3 of 10. Access expires 2024-02-15T10:30:00.000Z."
  }
}

Each call to this endpoint increments the download count. Downloads are limited to prevent abuse.

Example

curl "https://api.priv.io/v1/marketplace/wallet/purchases/purchase_xyz789/download?access_token=at_abc123..." \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

JavaScript Examples

Complete Purchase Flow

// Browse listings
async function browseListings(filters = {}) {
  const params = new URLSearchParams(filters);
  const response = await fetch(
    `https://api.priv.io/v1/marketplace/wallet/listings?${params}`,
    { headers: { 'Authorization': `Bearer ${token}` } }
  );
  return response.json();
}

// Purchase a listing
async function purchaseListing(listingId: string) {
  const response = await fetch(
    `https://api.priv.io/v1/marketplace/wallet/listings/${listingId}/purchase`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ access_duration_days: 30 }),
    }
  );

  const data = await response.json();

  if (!data.success) {
    throw new Error(data.error.message);
  }

  return {
    purchaseId: data.data.purchase_id,
    accessToken: data.data.access_token,
    expiresAt: data.data.expires_at,
  };
}

// Download purchased data
async function downloadPurchase(purchaseId: string, accessToken: string) {
  const response = await fetch(
    `https://api.priv.io/v1/marketplace/wallet/purchases/${purchaseId}/download`,
    {
      headers: {
        'Authorization': `Bearer ${token}`,
        'X-Access-Token': accessToken,
      },
    }
  );

  const data = await response.json();

  // Download each file
  for (const file of data.data.downloads) {
    console.log(`Downloading: ${file.filename}`);
    const fileResponse = await fetch(file.gateway_url);
    const blob = await fileResponse.blob();
    // Save blob to file system or process as needed
  }

  return data.data;
}

Create and Publish Listing

async function createAndPublishListing(
  contributions: string[],
  title: string,
  description: string,
  price: number
) {
  // Create draft listing
  const createResponse = await fetch(
    'https://api.priv.io/v1/marketplace/wallet/listings',
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        title,
        description,
        category: 'photo',
        price_priv: price,
        contribution_ids: contributions,
      }),
    }
  );

  const createData = await createResponse.json();
  const listingId = createData.data.listing_id;

  // Submit for review
  const publishResponse = await fetch(
    `https://api.priv.io/v1/marketplace/wallet/listings/${listingId}`,
    {
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        status: 'pending_review',
      }),
    }
  );

  return publishResponse.json();
}