βοΈLabs API
Overview
The Labs API allows developers to interact with 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 uses consumer-credential authentication for reads and an additional Service Token for writes. Full details β public queries vs. protected mutations, obtaining and using credentials β are on the Authentication page.
See also the functional sections: Lab Management, Files, Browse & Search, Legal Agreements, and Service Tokens. For a full end-to-end walkthrough β mint a LabNFT, register its dataroom, sign the assignment agreement, then encrypt and upload a file β see Example Workflow.
Error Handling
The Labs API is a GraphQL API: once a request is accepted, the response is HTTP 200 whether or not the operation succeeded β success and failure are signalled inside the JSON body, not by the status code. Errors surface through one of two channels, depending on the operation class:
Queries throw. A failed query adds an entry to the top-level GraphQL
errors[]array and returnsnullfor that field. Most Labs query result types are non-null, so the null propagates anddataitself comes backnull(as in the example below); onlylabWithDataRoomAndFilesanddataRoomFileare nullable and null just their own field.errorTypecarries the error code (the only value to branch on) anderrorInfocarries{ requestId, retryable, details }.Mutations return errors in-band. Every mutation result type carries an
error: ApiErrorfield. Success βerror == null. Where the result type also has a top-levelmessage, it mirrorserror.messageon failure and is never empty. A top-levelerrors[]entry on a mutation means a transport or infrastructure failure, or that the request document itself failed validation.
Branch on the code β never on message text, which may change without notice. Include requestId whenever you report a problem.
Failed Query
Failed Mutation
Select error { code message requestId retryable details } on every mutation:
In-band details is a JSON-encoded string β parse it with JSON.parse(error.details ?? "{}") (on thrown queries, errorInfo.details is already an object). Documented keys are field (the offending input field), reason (a more specific cause under the code, e.g. PROJECT_NOT_FOUND under NOT_FOUND), hint and docs; ignore unknown keys. reason values are diagnostic refinement and may be extended at any time β branch on code first.
Error Codes
Code
retryable
Meaning
UNAUTHENTICATED
false
Missing, invalid or expired credentials
UNAUTHORIZED
false
Authenticated, but not allowed (role/membership)
NOT_FOUND
false
Referenced resource doesn't exist
VALIDATION_FAILED
false
Input failed validation (unknown filter/sort fields, out-of-range pagination, malformed ids); details.field names the offender
CONFLICT
false
Valid request conflicts with current state (e.g. details.reason SHORTNAME_TAKEN, ALREADY_SIGNED)
FAILED_PRECONDITION
false
Resource state makes the operation impossible until the state changes (e.g. TEMPLATE_EXPIRED)
COMPLEXITY_LIMIT_EXCEEDED
false
Query shape or result size over limits
RATE_LIMITED
true
Throttled β retry with backoff
TIMEOUT
true
Execution exceeded the request budget
UPSTREAM_UNAVAILABLE
true
A dependency failed (details.reason KAMU, CMS, IPFS)
INTERNAL_ERROR
true
Unexpected failure β details are only in our logs, joined by requestId
When retryable is true, retry with exponential backoff; when false, the request (or the resource state) must change before retrying. Any code not listed here: preserve it for diagnostics, treat it as non-retryable and surface it to a human β new codes are announced in the API Changelog. PAYMENT_REQUIRED is reserved for the x402 Gateway and is not emitted by the GraphQL API.
Troubleshooting
UNAUTHENTICATED β missing, invalid or expired service token:
Ensure the
X-Service-Tokenheader is included in mutation requestsVerify the token is not empty or malformed
If the token has expired, request a new token from the Molecule team, or use the
extendServiceTokenmutation to extend expiration
A missing or malformed consumer credential is rejected before the GraphQL layer runs (an HTTP 401 from the API, not one of the error codes below) β check the Authorization header first, see Authentication.
UNAUTHORIZED β the wallet behind the service token lacks the required role on the lab:
Verify your wallet address (linked to the service token) has admin access to the lab/dataroom (or the role the operation requires)
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)
NOT_FOUND β lab, dataroom or file not found:
Verify the
oclIdrefers to a registered labFor
updateFileMetadata/deleteDataRoomFile: verify the fileref(DID) orpathis correct and the file exists in the specified dataroom
VALIDATION_FAILED β invalid parameters; details.field names the offending input:
Check that the
oclIdformat is correct: a 32-byte hex string with0xprefixFor
searchLabs: verify filter values match expected types (arrays of strings)
Retryable errors (RATE_LIMITED, TIMEOUT, UPSTREAM_UNAVAILABLE, INTERNAL_ERROR):
Retry with exponential backoff; if the failure persists, report it with the
requestId
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
updateFileMetadatato refine tags and descriptions without re-uploading files
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 & Renamed Operations
The legacy *V2 operations and the pre-OCL naming have been removed. The current API is oclId-based. If you are migrating from an older integration, see the query/mutation/field rename tables in the API Changelog & Migration page.
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
Last updated: July 2026
Last updated