โ๏ธLabs API
Overview
The Programmatic File Upload API allows developers to automate file uploads to Molecule Labs datarooms without requiring browser-based user interaction. This enables integration with automated workflows, data pipelines, CI/CD systems, and external applications.
Use Cases
Automated Data Pipelines: Schedule regular data synchronization from research systems
CI/CD Integration: Automatically publish build artifacts and test results
External System Integration: Connect third-party tools and platforms to your Lab
Batch Operations: Upload multiple files programmatically
Monitoring & Alerting: Automated upload of logs and metrics
Ready for Production: This API is production-ready and actively used by projects for automated data management. To request API access, please join our Discord community and reach out to our team.
Authentication
The Labs API requires two authentication headers for all requests:
API Key - For general API authentication
Service Token - For lab-specific access control
Obtaining API Key and Service Token
To obtain access credentials:
Join our Discord community
Contact the Molecule team and provide:
Your wallet address (will be linked to the service token)
Intended use case / service name
Which lab/dataroom you need access to
Desired token expiration period
The team will generate and provide you with:
API Key - Used for all Molecule APIs
Service Token (JWT string) - Grants access to specific lab
Token ID - For management operations
Using Your Credentials
Both headers are required for all Labs API requests:
Why two tokens?
API Key: Authenticates you as a valid Molecule API user
Service Token: Identifies which specific lab/dataroom you have access to
Security Warnings:
Service tokens are shown only once during generation - store them securely immediately
Never commit tokens or API keys to version control
Never log credentials in application logs
Store in environment variables or secure secret management systems
Rotate tokens regularly (quarterly recommended)
API Endpoints
The Programmatic File Upload API uses a 3-step workflow:
API Base URL
Step 1: Initiate File Upload
Initiates the upload process and returns a presigned URL for direct file upload.
GraphQL Mutation:
Parameters:
ipnftUid
String
Yes
IP-NFT unique identifier in format contractAddress_tokenId (e.g., 0xcaD...1_37)
contentType
String
Yes
MIME type of the file (e.g., application/pdf, image/png)
contentLength
Int
Yes
File size in bytes
Example Request (curl):
Success Response:
Step 2: Upload File to Storage
Upload the file directly to the presigned URL returned in Step 1.
Example Request (curl):
Example Request (JavaScript):
Step 3: Finish File Upload
Completes the upload process and registers the file in the dataroom.
GraphQL Mutation:
Parameters:
ipnftUid
String
Yes
Same IP-NFT identifier used in Step 1
uploadToken
String
Yes
Token received from Step 1
path
String
No*
File name for NEW files (e.g., research-data.pdf)
ref
String
No*
Dataset ID for NEW VERSIONS of existing files
accessLevel
String
Yes
File visibility: PUBLIC, HOLDERS, or ADMIN
changeBy
String
Yes
Wallet address of user making the change
description
String
No
Optional file description
tags
[String]
No
Optional tags for categorization
categories
[String]
No
Optional categories for organization
contentText
String
No
Optional searchable text content (used for semantic search)
*Use path for new files OR ref for versions - not both
Example Request (curl):
Success Response:
Update File Metadata
Update file metadata (description, tags, categories, access level) without creating a new version.
GraphQL Mutation:
Parameters:
ipnftUid
String
Yes
IP-NFT unique identifier
ref
String
Yes
File reference (DID) from finishCreateOrUpdateFileV2 response
accessLevel
String
Yes
File visibility: PUBLIC, HOLDERS, or ADMIN
description
String
No
Updated file description
tags
[String]
No
Updated tags for categorization
categories
[String]
No
Updated categories for organization
contentText
String
No
Updated searchable text content
Note: The
changeByfield (wallet address) is automatically derived from your authentication and does not need to be provided as a parameter.
Example Request:
Delete File
Remove a file from the dataroom permanently.
GraphQL Mutation:
Parameters:
ipnftUid
String
Yes
IP-NFT unique identifier
path
String
Yes
File path to delete
changeBy
String
Yes
Wallet address making the deletion
Warning: This is a destructive operation. The file will be permanently deleted from the dataroom and cannot be recovered.
Example Request:
Create Announcement
Create project announcements to share updates with your community.
GraphQL Mutation:
Parameters:
ipnftUid
String
Yes
IP-NFT unique identifier
headline
String
Yes
Announcement title/headline
body
String
Yes
Announcement body (supports Markdown)
attachments
[String]
No
Array of file DIDs to attach to the announcement
Example Request:
Querying Projects and Files
Query operations for browsing projects, viewing files, and checking activity.
List All Projects
Get all IP-NFT projects available to you.
GraphQL Query:
Example Request:
Get Single Project with Files
Retrieve complete details for a specific project including all files.
GraphQL Query:
Example Request:
Get File by Path
Retrieve a specific file using IP-NFT UID and file path.
GraphQL Query:
Example Request:
Project Activity Feed
Get activity timeline for a specific project including file events and announcements.
GraphQL Query:
โ ๏ธ Breaking Change: Announcement
attachmentschanged from[String!]!(array of DIDs) to[DataRoomFile!]!(array of file objects). This enables querying file metadata directly without separate API calls.
Example Request:
Performance Note: Attachment fields in projectActivityV2 are limited to essential display fields (did, path, name, contentType, accessLevel) for optimal performance. For full attachment metadata including downloadUrl and encryption details, use projectAnnouncementsV2 instead.
Project Announcements (Dedicated Endpoint)
Get announcements for a specific project with full attachment details. More efficient than projectActivityV2 when you only need announcements.
GraphQL Query:
Example Request:
Use Cases:
Announcement detail pages requiring full file metadata
Download links for announcement attachments
Encrypted file access with Lit Protocol
Projects with many announcements (efficient pagination)
All Announcements (Global Feed)
Get all announcements across all projects.
GraphQL Query:
Note: Attachment fields in
activitiesV2are limited for performance. UseprojectAnnouncementsV2for full attachment metadata including downloadUrl.
Searching Labs
Perform semantic search across all projects, files, and announcements in the Labs ecosystem.
GraphQL Query:
Parameters:
prompt
String
Yes
Search query text
filters
SearchLabsFilters
No
Filter criteria
page
Int
No
Page number (default: 0)
perPage
Int
No
Results per page (default: 10)
Available Filters:
byIpnftUids
[String!]
Filter by specific project UIDs
byTags
[String!]
Filter files by tags
byCategories
[String!]
Filter files by categories
byAccessLevels
[String!]
Filter files by access level (PUBLIC, HOLDERS, ADMIN)
byKinds
[String!]
Filter by result type
Example - Basic Search:
Example - Filtered Search:
Understanding Results:
Search results are returned as a union type. Use the __typename field to determine result type:
SearchLabsFileHit: File search result
Access via:
entry.fileContains: file metadata, tags, categories, download URL
SearchLabsAnnouncementHit: Announcement search result
Access via:
announcementContains: headline, body, project reference, typed attachments (file objects)
JavaScript Example:
Complete Example
Here's a complete Node.js example demonstrating the full 3-step workflow:
Usage:
Service Token Management
Obtaining Tokens
Service tokens must be requested from the Molecule team (see Authentication section above).
Extending Token Expiration
You can extend your service token's expiration using the extendServiceToken mutation:
Parameters:
tokenId
String
Token ID provided when token was generated
expiresIn
String
New duration (e.g., "30d", "720h", "90d")
Example:
Important: Extension returns a new JWT token - update your stored token accordingly.
Revoking Tokens
Revoke a service token immediately (e.g., if compromised):
Example:
Error Handling
All API responses follow a consistent error format:
Error Response Structure
Common Error Codes
401
Unauthorized
Missing or invalid service token
403
Forbidden
Service token does not have access to the specified IP-NFT
400
Bad Request
Invalid parameters (e.g., missing ipnftUid, invalid contentType)
404
Not Found
IP-NFT or dataroom not found
413
Payload Too Large
File exceeds size limits
500
Internal Server Error
Server error - check if retryable and try again
Troubleshooting
"Missing service token" error:
Ensure
X-Service-Tokenheader is included in requestsVerify token is not empty or malformed
"Service does not have access to IPNFT" error:
Verify your wallet address (linked to service token) has admin access to the IP-NFT/dataroom
Check that the ipnftUid format is correct:
contractAddress_tokenId
"Token expired" error:
Request a new token from the Molecule team, or
Use
extendServiceTokenmutation to extend expiration
Upload to presigned URL fails:
Ensure binary file upload (use
--data-binaryin curl)Verify headers match those returned in Step 1
Check that presigned URL hasn't expired (expires after ~15 minutes)
"File not found" error (updateFileMetadataV2, deleteDataRoomFileV2):
Verify the file
ref(DID) orpathis correctCheck that the file exists in the specified dataroom
Ensure you have access to the dataroom
"Invalid search filters" error (searchLabs):
Verify filter values match expected types (arrays of strings)
Check that access level values are: PUBLIC, HOLDERS, or ADMIN
Ensure ipnftUid format is correct if using byIpnftUids filter
File Requirements & Limits
Storage Limits
Default Limit: 5GB per lab/project
Custom Limits: Can be increased upon request - contact the Molecule team
Supported File Types
All file types are supported
Common types: PDF, PNG, JPEG, CSV, JSON, ZIP, etc.
Access Levels
PUBLIC
Visible to anyone with access to the project
HOLDERS
Visible only to IP Token (IPT) holders
ADMIN
Visible only to project administrators
Optional Metadata
Enhance file discoverability with optional metadata:
description: Human-readable description of the file
tags: Array of tags for categorization (e.g.,
["research", "q4-2024"])categories: Array of categories for organization (e.g.,
["data", "results"])contentText: Searchable text content for full-text search
Advanced: Encrypted File Upload
For files requiring client-side encryption, you can include encryption metadata using the Lit Protocol.
Encryption Metadata Parameter
Structure:
When to Use Encryption:
Sensitive research data requiring access control
Compliance requirements for data protection
Conditional access based on token ownership
For more information about Lit Protocol encryption, visit the Lit Protocol documentation.
Best Practices
Token Security
Never commit tokens to version control (add to
.gitignore)Use environment variables to store tokens
Rotate tokens regularly (quarterly recommended)
Use secrets management systems in production (AWS Secrets Manager, HashiCorp Vault, etc.)
Revoke immediately if a token is compromised
Storage Management
Monitor your 5GB storage limit per project
Organize files with meaningful names and metadata
Use categories and tags for easy file discovery
Clean up old or unnecessary files regularly
Metadata Best Practices
Use descriptive tags:
["experiment-1", "2024-q4", "preliminary"]Organize with categories:
["raw-data", "analysis", "results"]Add descriptions: Help collaborators understand file contents
Include searchable text (
contentText): Enables full-text search viasearchLabsUpdate metadata as needed: Use
updateFileMetadataV2to refine tags and descriptions without re-uploading files
Access Control
Use
ADMINfor sensitive internal documentsUse
HOLDERSfor IPT holder-exclusive contentUse
PUBLICfor community-facing dataReview access levels regularly as your project evolves
Search and Discovery
Use contentText: Populate
contentTextfield when uploading files to enable full-text searchTag consistently: Use consistent tag names across files for better filtering
Filter strategically: Combine filters (tags + access levels) to narrow search results
Test search queries: Use
searchLabsto verify your files are discoverable
Deprecated Operations
The following V1 operations have been replaced by improved V2 versions. V1 operations are deprecated and will be removed in a future release.
Deprecated Queries
projects
projectsV2
Added systemTime and eventTime fields
projectWithDataRoomAndFiles
projectWithDataRoomAndFilesV2
Enhanced temporal tracking
dataRoomFile(did: String!)
dataRoomFileV2(ipnftUid, path)
Query by IPNFT UID + path instead of DID
projectActivity
projectActivityV2
Improved activity feed structure
activities
activitiesV2
Enhanced announcement structure
Deprecated Mutations
initiateFileUpload
initiateCreateOrUpdateFileV2
Simplified parameters, no dataset alias needed
finishFileUpload
finishCreateOrUpdateFileV2
Added metadata support (tags, categories, contentText)
deleteDataRoomFile
deleteDataRoomFileV2
Streamlined parameters
createAnnouncement
createAnnouncementV2
Breaking: Removed moleculeAccessLevel parameter
Migration Guide
Breaking Change 1: createAnnouncement โ createAnnouncementV2
The moleculeAccessLevel parameter has been removed in V2:
Breaking Change 2: Announcement Attachments Type Change
โ ๏ธ BREAKING CHANGE: Announcement attachments changed from string arrays to full file objects.
Previous Structure (V1):
New Structure (V2):
Migration Required: If you query announcements via projectActivityV2, activitiesV2, searchLabs, or projectAnnouncementsV2, update your code to handle attachment objects instead of strings:
Before:
After:
Benefits:
โ No additional API calls needed for file metadata
โ Better developer experience
โ Reduced API load
โ Type-safe attachment handling
Field Availability by Query:
projectActivityV2
Minimal (did, path, name, contentType, accessLevel)
activitiesV2
Minimal (did, path, name, contentType, accessLevel)
searchLabs
Minimal (did, path, name, contentType, accessLevel)
projectAnnouncementsV2
Full (includes downloadUrl, encryptionMetadata, version, etc.)
All other V1 โ V2 migrations are backward-compatible with additional optional parameters in V2.
Getting Support
If you encounter any issues or have questions about the Programmatic File Upload API:
Check this documentation and troubleshooting section
Review the complete example for implementation guidance
Join our Discord community for support
Contact the Molecule Labs development team directly
Recent Updates (January 2025)
New Features
๐ New Query: searchLabs
searchLabsSemantic search across all IP-NFT projects, files, and announcements:
Full-text search with relevance ranking
Filter by tags, categories, access levels, project UIDs
Returns unified results (files + announcements)
Paginated results with totalCount
Benefits:
Discover content across all Labs projects
Filter by multiple criteria simultaneously
Unified search experience
Support for complex queries
See Searching Labs section for complete documentation.
๐ New Mutation: updateFileMetadataV2
updateFileMetadataV2Update file metadata without creating a new version:
Modify description, tags, categories, contentText
Update access level (PUBLIC, HOLDERS, ADMIN)
No file re-upload required
Preserves version history
Benefits:
Refine file metadata after upload
Improve searchability with updated contentText
Reorganize files with new tags/categories
Adjust access control as needed
See Update File Metadata section for complete documentation.
โจ New Query: projectAnnouncementsV2
projectAnnouncementsV2Added dedicated announcements endpoint with full attachment metadata:
Fetches ONLY announcements (no file events) for better performance
Includes complete attachment details (downloadUrl, encryptionMetadata, etc.)
Efficient pagination with totalCount
Use this instead of projectActivityV2 when you only need announcements
Benefits over projectActivityV2:
Faster response times
Full attachment metadata available
Direct pagination support
No file events to filter through
๐ Pagination Enhancement: projectActivityV2
projectActivityV2Added pageInfo object to projectActivityV2 results:
Enables proper client-side pagination with total page count.
Breaking Changes
โ ๏ธ Announcement Attachments Type Change (IP-1025)
Affected Queries: projectActivityV2, activitiesV2, searchLabs, projectAnnouncementsV2
What Changed:
Attachments field type:
[String!]!โ[DataRoomFile!]!Instead of array of DIDs, you now get full file objects
Before (Old):
After (New):
Why This Change:
โ Eliminates need for separate API calls to resolve file details
โ Improves developer experience
โ Reduces API load and complexity
โ Type-safe file handling
Migration: Update your code to access file properties directly instead of using DIDs to fetch file details:
Field Availability:
Activity queries (projectActivityV2, activitiesV2, searchLabs): Minimal fields (6 fields for performance)
Announcements query (projectAnnouncementsV2): Full fields (20+ fields including downloadUrl)
Performance Improvements
๐ Optimized Activity Query Performance
Reduced attachment fields in activity/search queries to prevent Lambda timeouts:
Minimal Fields (Activity Queries):
Essential:
id,did,path,name,contentType,accessLevelRemoved:
downloadUrl,encryptionMetadata,contentText,version,contentHash, etc.
Result: Faster response times, no timeout issues
Full Fields Available: Use projectAnnouncementsV2 when you need downloadUrl, encryptionMetadata, or other detailed fields.
Internal Improvements
๐ง Path Field Consistency (IP-1352)
Fixed inconsistency where the path field differed between queries:
Now consistently uses Kamu's native
pathfieldImproved
namefield priority:dataset.nameโdescriptionโpath-derived
Impact: More consistent file paths across all queries
Last updated: January 2025
Last updated