What is Chipotle?
Chipotle is a REST API and web dashboard for confidential compute and programmable key management. It comprises three composable layers:
- TEE Enclave — holds the root key, derives signing and encryption keys on demand, and executes sandboxed JavaScript. Nothing that touches key material ever leaves the enclave.
- On-Chain Permissions (Base) — all authorization state lives on-chain: accounts, API key scopes, PKP registrations, and groups.
- Lit Actions (IPFS) — immutable JavaScript programs stored by content ID (CID). Public, content-addressed, tamper-proof.
Think of it as serverless functions that can hold private keys.
For Web3 developers
Write a Lit Action in plain JavaScript. It can sign transactions, encrypt and decrypt secrets, read on-chain state, fetch external APIs, and return cryptographically signed proofs — all governed by on-chain permission groups.
For traditional developers
A REST API with a JS SDK. Create an account, get an API key, call one endpoint. No wallets, no MetaMask, no Solidity required.
Quickstart
Five steps against the live API. No SDK needed — just curl. Steps 3–5 consume credits, so you'll fund the account in step 2 (read-only calls are always free).
1. Create an account
curl -s -X POST https://api.chipotle.litprotocol.com/core/v1/new_account \
-H "Content-Type: application/json" \
-d '{"account_name": "my-app", "account_description": "Getting started"}' | jq
{
"api_key": "T6j+7BAA…",
"wallet_address": "0x3318…b0c5"
}
This call takes ~15 seconds — it registers your account on-chain (Base) before returning. Everything after it is sub-second. Your account starts with one wallet already attached: wallet id 0, the Account Master Wallet shown in the response.
2. Add funds
Lit Action execution and write/metered management operations require credits. Add funds in the Dashboard — click Add Funds in the top-right corner and select a credit package (minimum $5.00). Pay with a credit card, crypto (ETH, USDC, SOL and more), or LITKEY. See Pricing for details.
Skipping this step? Steps 3–5 will answer 402 Payment Required — the error body tells you exactly how to fund. See Errors.
3. Create a usage API key
Your account key is the master credential — don't embed it in apps. Create a scoped usage key instead:
curl -s -X POST https://api.chipotle.litprotocol.com/core/v1/add_usage_api_key \
-H "Content-Type: application/json" \
-H "X-Api-Key: $API_KEY" \
-d '{
"name": "My dApp Key",
"description": "Getting started",
"can_create_groups": false,
"can_delete_groups": false,
"can_create_pkps": true,
"manage_ipfs_ids_in_groups": [],
"add_pkp_to_groups": [],
"remove_pkp_from_groups": [],
"execute_in_groups": [0]
}' | jq
{
"usage_api_key": "Xk9m+2CA…"
}
Save this key — it's shown only once. Use it in place of your account key for the remaining steps. See API Keys for details on scoping permissions.
4. Create a wallet (PKP)
curl -s -X POST https://api.chipotle.litprotocol.com/core/v1/create_wallet \
-H "X-Api-Key: $API_KEY" | jq
{
"wallet_address": "0x2a03…9bf6"
}
5. Run a Lit Action
curl -s -X POST https://api.chipotle.litprotocol.com/core/v1/lit_action \
-H "X-Api-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"code": "async function main() { return { hello: \"world\", timestamp: Date.now() }; }"
}' | jq
{
"response": { "hello": "world", "timestamp": 1711684200000 },
"logs": "",
"has_error": false
}
Or skip the terminal and use the Dashboard — a full GUI for account management, wallet creation, and action execution.
What can you build?
Lit Actions are immutable JavaScript programs stored on IPFS and executed inside the TEE with access to derived keys. They can sign data, encrypt and decrypt secrets, make HTTP requests, and return cryptographically attested results.
// Fetch a live price and sign it as a verifiable proof
async function main({ pkpId }) {
const res = await fetch(
"https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd"
);
const price = (await res.json())?.ethereum?.usd;
const wallet = new ethers.Wallet(
await Lit.Actions.getPrivateKey({ pkpId })
);
const signature = await wallet.signMessage(`ETH/USD: ${price}`);
return { price, signature };
}
A smart contract can ecrecover the signature to confirm the price was attested by a known PKP — no off-chain trust required.
See the full Examples guide for copy-paste code.
API surface
Every endpoint accepts X-Api-Key or Authorization: Bearer <key>. The Core API is mounted at /core/v1/.
Full OpenAPI spec: /core/v1/swagger-ui
Key endpoints
POST /core/v1/new_account Create an account → { api_key, wallet_address }
POST /core/v1/create_wallet Mint a new PKP wallet
POST /core/v1/lit_action Execute JavaScript in the TEE
POST /core/v1/add_action Register a Lit Action (IPFS CID or inline)
POST /core/v1/add_group Create a permission group
GET /core/v1/list_wallets List all PKP wallets for the account
GET /core/v1/list_actions List registered Lit Actions
GET /core/v1/version Server version and commit hash
Errors are always JSON — { "error", "message", "fix", "docs_url" } — with the status codes documented in the Errors reference. Failed requests are never charged.
Local development
local_test.sh spins up the full stack locally against a throwaway Anvil chain. It starts six services and tears them all down on Ctrl+C.
Prerequisites
Run
./local_test.sh
The script will:
- Start Anvil (local Ethereum node on
http://127.0.0.1:8545) - Start the dstack simulator (creates a temp dir under
/tmp/dstack-sim-*) - Deploy contracts to Anvil and write
lit-api-server/NodeConfig.toml cargo runlit-api-server (http://localhost:8000)cargo runlit-actions (Unix socket at/tmp/lit_actions.sock)- Serve lit-static via static-web-server (
http://localhost:8080)
Press Ctrl+C to stop all services.
Configuration
Billing in local development
By default a local (non-production) build of lit-api-server requires a configured
test Stripe account so the billing path is actually exercised instead of silently running
payment-free (CPL-330). On startup the server will refuse to run when:
- the Stripe keys are missing, or
- the keys are not role-correct test keys. The secret must start with
sk_test_orrk_test_and the publishable must start withpk_test_. This rejects live keys (so a dev machine can't charge real cards), arbitrary non-Stripe strings (which would otherwise start "in test mode" and only fail on the first real request), and a secret key mistakenly placed inSTRIPE_PUBLISHABLE_KEY(which is served to unauthenticated clients viaGET /billing/stripe_config).
Set both STRIPE_SECRET_KEY (test) and STRIPE_PUBLISHABLE_KEY (test) before starting the
server. To run payment-free anyway, set LIT_DISABLE_BILLING=true.
Architecture
See the Architecture overview and Authentication model in the docs.
Features
Links
License
All rights reserved. Copyright Lit Protocol.