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

Getting Started

What a Lab is, what you need before your first call, and a ten-minute path to a lab with a file in it.

The Molecule API lets you create a Lab β€” a research project with its own onchain identity and its own file store β€” and then read and write that Lab's files from code.

This page covers the two things you need before your first call, which way of calling the API fits you, and a ten-minute path that ends with a lab you can open in a browser.

New to the Molecule ecosystem? The Glossary defines every term used in these guides β€” Lab, LabNFT, oclId, data room, service token, indexer β€” in a sentence or two each. Worth keeping open in a second tab.

Everything here runs against staging (Base Sepolia, testnet funds), so nothing spends real money. Moving to mainnet later is a matter of swapping a handful of constants: Running in Production.


Choose how you'll call the API

Three ways in. None is better than the others β€” pick by who is making the calls.

If this is you
What you'll use
Start here

You're writing a script in Node/TypeScript and want to see the raw calls

GraphQL requests plus viem for the one onchain step

You run an AI coding agent (Claude Code, Codex, Cursor) and want it to do the whole workflow for you

The Molecule Skill plugin, which wraps every network, onchain and crypto operation as a single tool call

You'd rather pay per call than hold a long-lived credential

The x402 gateway, which settles USDC on Base per request

These combine rather than compete β€” choosing one now doesn't lock you out of the others. A common setup is the plugin for the workflow and x402 for the calls that cost money. Check out Common Use Cases for the path through these docs for what you're building.

If you are an agent reading this

Go to the Agent one-pager instead. It is the whole default flow on a single page with no prose detours β€” written to be pasted into a system prompt.


The tutorials

Each one is runnable end to end against staging, and shows the expected response and the failure modes at every step.

Tutorial
What you have when you finish

A Lab of your own, with a public file in it

A confidential file that only certain people that you specify can decrypt

An agent writing into a Lab that a human owns

All three open with the same configuration constants and helper functions, which live on one page: Shared Setup. Copy that block once and every snippet in the tutorials runs against it.


Prerequisites

Two things, and only one of them involves a human.

A consumer credential (the one manual step)

Every request to the API carries a consumer credential in the Authorization header. Until the Developer Portal ships (coming soon), you will need to request this from the Molecule team.

Sign in at labs.molecule.xyz with an account that has an email address, open API Keys, and click Request access. The team replies by email within one business day. In your reply, say whether you need staging, production, or both β€” every tutorial in these docs runs on staging.

What comes back is a single opaque string per environment:

Send it as the Authorization header value directly β€” no Bearer prefix:

Treat the whole string as one secret: it is not split into a public and a private half. Full header reference: Authentication.

A funded wallet on Base Sepolia

You only need this if you are creating a new Lab from code. Creating a Lab means minting a LabNFT, which is an onchain transaction, and the wallet that sends it pays the gas. If you create your Lab in the Molecule app instead, you need no funds at all β€” Molecule covers those transactions for you. The app is at labs.molecule.xyz, or testnet.labs.molecule.xyz for the Base Sepolia environment these tutorials run against.

For the programmatic path you need an EOA β€” an ordinary wallet with a private key β€” holding testnet ETH on Base Sepolia. Fund it from a Base Sepolia faucet.

If β€” and only if β€” you are using the x402 gateway, you also need testnet USDC on Base Sepolia: get it from the Circle faucet (select Base Sepolia). Paying with a service token needs no USDC at all.

You do not need a pre-issued service token β€” it is proof that you control a particular wallet, and every tutorial issues its own by signing a message in its first step. What it is, what it authorizes and how it is sent: Authentication.

What it costs

Item
Cost

LabNFT mint

Gas only, on Base Sepolia and on Base mainnet. Read the fee live with mintFeeWei() and, if it is ever non-zero, send it as value β€” the tutorials already do this, so a future fee needs no code change on your side

createLab, uploads and other content writes

Free

The same mutations through the x402 gateway

Quoted per request in the 402 challenge, currently $0.01 USDC on both environments. Read the price off the challenge rather than hardcoding it

Storage

5 GB per lab included β€” see Limits

Tooling

Or, if you are using the Molecule Skill plugin, install mol-labs-plugin and run config_doctor β€” it names exactly which configuration is still missing instead of letting a tool guess:


Ten-minute quickstart

The shortest path from "I have a credential" to "there is a lab with my file in it". Four API calls and one transaction. Each step below is the condensed form of Create a lab and upload a public file, which shows the expected response and the failure modes for every call.

  1. Issue yourself a service token β€” getServiceSignInMessage β†’ sign the message with your wallet (EIP-191 personal_sign) β†’ generateServiceToken. No human in the loop. Keep the three calls together: the message carries a single-use nonce valid for 10 minutes.

  2. Mint the LabNFT β€” OnChainLabFactory.mintAndCreateAccount(yourAddress) with value: mintFeeWei(). Read oclId off the OclIdentityCreated event.

  3. Register the lab β€” createLab(input: { oclId }). This attaches the data room your files will live in.

  4. Upload a file β€” initiateCreateOrUpdateFile β†’ PUT the bytes to the returned presigned URL β†’ finishCreateOrUpdateFile with accessLevel: "PUBLIC".

  5. Verify it worked β€” see below.

The runnable version is the complete script:

Verify it worked

Two checks. The first works on every environment and needs nothing but your credential:

Your file appears in dataRoom.files with the path you sent and accessLevel: "PUBLIC". If labWithDataRoomAndFiles comes back null, createLab did not complete β€” a missing lab nulls the field rather than throwing an error.

The second check is visual β€” the lab has a page of its own, at /projects/<slug>:

Environment
Lab page

Staging

https://testnet.labs.molecule.xyz/projects/<slug>

Production

https://labs.molecule.xyz/projects/<slug>

Until the lab is renamed, that slug is lab-<tokenId>, built from the labNftTokenId that createLab returns β€” so a lab you have just created is at .../projects/lab-1274. Once the owner renames the lab, the slug becomes the shortname derived from the new name, and the lab-<tokenId> form stops resolving.

Do not build this URL from oclId. It identifies the lab in API calls, it is not a page slug, and it does not resolve here.


Running in Production

The tutorials all run against staging (Base Sepolia, testnet funds). To run the same scripts against production, replace the values in the Shared Setup config block β€” nothing else changes, because every step reads from these constants:

Constant
Staging (these tutorials)
Production

GRAPHQL_URL

https://staging.graphql.api.molecule.xyz/graphql

https://production.graphql.api.molecule.xyz/graphql

CHAIN (viem import)

baseSepolia from viem/chains

base from viem/chains

FACTORY_ADDRESS

0xd629FE2310b4309a212495F10A47f8436dcEfD90

0xECdF4f05384056507485C90aeAb0a83268760D6E

LABNFT_ADDRESS

0x13Ff210695fdb54A7F928ECcc28BC3486c05BB28

0x9F96027eeAFb9ad5F2b5d7043B36Ee96B2EeBE92

ACCESS_RESOLVER_ADDRESS

0x5493F472602C87318EA5Eff753cDD593bf9bF559

0x89a14Be8f7824d4775053Edad0f2fA2d6767b72B

ACCESS_CONDITION_CHAIN

"baseSepolia"

"base"

LAB_APP_URL

https://testnet.labs.molecule.xyz

https://labs.molecule.xyz

A few things follow automatically from that swap:

  • Headers and the graphql() helper are identical β€” Authorization (consumer credential, no Bearer) and the self-issued X-Service-Token work the same against both endpoints. Note that credentials are per environment: a staging mol_ credential does not authenticate against production.

  • The mintFeeWei() read already queries the live contract, so it picks up whatever fee production has configured with no code change.

  • The access-condition ABIs are unchanged; only contractAddress and chain differ, and both come from the config block.

What doesn't follow automatically, and is on you:

  • Real funds. Minting on base spends real ETH. Test on staging first.

  • Introspection is off in production and query depth is capped at 10. Generate types against staging β€” see Getting the schema. The other differences between the two environments are on Rate & Query Limits.

  • SERVICE_NAME should identify the real integration; it is echoed into the sign-in message and stored against the issued token.

  • Full deployment list, including every other OCL contract on both chains: Contracts reference.


Getting the schema

Staging has GraphQL introspection enabled β€” point codegen, a playground or an SDK generator straight at it:

Introspection requires only the Authorization consumer-credential header, the same as any query.

Production has introspection disabled, deliberately β€” __schema and __type return a validation error there (__typename still resolves). Generate against staging and point the generated client at production; the two environments serve the same schema.

Production also enforces a query-depth limit of 10, which fails at execution time with errorType: "QueryDepthLimitReached" and partial data β€” a plain GraphQL error, not the catalogued shape. Handle both.


Where to go next

Next
Page

What every term in these guides means

The config and helpers every tutorial uses

Every operation, parameter and error code

What each error code means and how to read it

Paying per call, and the gateway base URLs

What a Lab actually is, onchain

Need help?

Ask the team on Discord. Reporting an API error? Include the requestId from the failing response so we can trace it.

Ask on Discord

Page wrong, unclear or missing something? Let us know with Was this helpful? on this page.

Last updated

Was this helpful?