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.
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.
You're writing a script in Node/TypeScript and want to see the raw calls
GraphQL requests plus viem for the one onchain step
The tutorials below
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.
Create a lab and upload a public file β start here
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.
Authorization: Bearer mol_β¦ fails authentication. Bearer is reserved for Privy user tokens.
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
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.
Issue yourself a service token β
getServiceSignInMessageβ sign the message with your wallet (EIP-191personal_sign) βgenerateServiceToken. No human in the loop. Keep the three calls together: the message carries a single-use nonce valid for 10 minutes.Mint the LabNFT β
OnChainLabFactory.mintAndCreateAccount(yourAddress)withvalue: mintFeeWei(). ReadoclIdoff theOclIdentityCreatedevent.Register the lab β
createLab(input: { oclId }). This attaches the data room your files will live in.Upload a file β
initiateCreateOrUpdateFileβPUTthe bytes to the returned presigned URL βfinishCreateOrUpdateFilewithaccessLevel: "PUBLIC".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>:
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:
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, noBearer) and the self-issuedX-Service-Tokenwork the same against both endpoints. Note that credentials are per environment: a stagingmol_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
contractAddressandchaindiffer, and both come from the config block.
What doesn't follow automatically, and is on you:
Real funds. Minting on
basespends 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_NAMEshould 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
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
Last updated
Was this helpful?