For the complete documentation index, see llms.txt. This page is also available as Markdown.

βš™οΈ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 returns null for that field. Most Labs query result types are non-null, so the null propagates and data itself comes back null (as in the example below); only labWithDataRoomAndFiles and dataRoomFile are nullable and null just their own field. errorType carries the error code (the only value to branch on) and errorInfo carries { requestId, retryable, details }.

  • Mutations return errors in-band. Every mutation result type carries an error: ApiError field. Success ⇔ error == null. Where the result type also has a top-level message, it mirrors error.message on failure and is never empty. A top-level errors[] 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-Token header is included in mutation requests

  • Verify the token is not empty or malformed

  • If the token has expired, request a new token from the Molecule team, or use the extendServiceToken mutation 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-binary in 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 oclId refers to a registered lab

  • For updateFileMetadata / deleteDataRoomFile: verify the file ref (DID) or path is correct and the file exists in the specified dataroom

VALIDATION_FAILED β€” invalid parameters; details.field names the offending input:

  • Check that the oclId format is correct: a 32-byte hex string with 0x prefix

  • For 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 via searchLabs

  • Update metadata as needed: Use updateFileMetadata to refine tags and descriptions without re-uploading files

Search and Discovery

  • Use contentText: Populate contentText field when uploading files to enable full-text search

  • Tag 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 searchLabs to 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:

  1. Check this documentation and troubleshooting section

  2. Review the complete example for implementation guidance

  3. Join our Discord community for support

  4. Contact the Molecule Labs development team directly


Last updated: July 2026

Last updated