Using the API directly
The same workflows can be done via the REST API. The API itself is under/core/v1/. All endpoints that require authentication expect the API key in a header:
X-Api-Key: your-api-key- or
Authorization: Bearer your-api-key
KEY=your_account_or_usage_api_key and BASE=https://api.chipotle.litprotocol.com (the hosted production API). The JavaScript examples use the Core SDK (LitNodeSimpleApiClient) from core_sdk.js.
API workflow:
- New account or verify account (login)
- Add funds (or via the billing API)
- Add usage API key
- Create wallet (PKP)
- Add group and register IPFS action
- Add PKP to group (optional)
- Run lit-action
1. New account or verify account (login)
Create a new account (returns API key and wallet address). Or verify an existing key with theaccount_exists function.
- JavaScript (Core SDK)
- cURL
3. Add usage API key
Create a usage API key with fine-grained permissions. The response includes the new key only once — store it immediately.- JavaScript (Core SDK)
- cURL
| Field | Type | Description |
|---|---|---|
can_create_groups | bool | Allow this key to create new groups |
can_delete_groups | bool | Allow this key to delete groups |
can_create_pkps | bool | Allow this key to create PKPs |
manage_ipfs_ids_in_groups | u64[] | Group IDs where this key can add/remove IPFS actions. Use [0] as a wildcard for all groups. |
add_pkp_to_groups | u64[] | Group IDs where this key can add PKPs. Use [0] for all groups. |
remove_pkp_from_groups | u64[] | Group IDs where this key can remove PKPs. Use [0] for all groups. |
execute_in_groups | u64[] | Group IDs where this key can execute lit-actions. Use [0] for all groups. |
4. Create a wallet (PKP)
Request a new wallet (PKP) for the account. The server returns the wallet address and registers it.- JavaScript (Core SDK)
- cURL
5. Add group and register IPFS action
Create a group, then add an action (IPFS CID) to scope which keys can run it.- JavaScript (Core SDK)
- cURL
6. Add PKP to group (optional)
Restrict which wallets (PKPs) can be used in the group by adding their IDs to the group.- JavaScript (Core SDK)
- cURL
7. Run lit-action
Execute a lit-action by sending JavaScript code and optional params. Use a usage API key (or account key) in the header.- JavaScript (Core SDK)
- cURL
Other useful endpoints
Raw CID vs hashed CID: Some endpoints accept a raw IPFS CID (
action_ipfs_cid, e.g. "QmYour...") — the server hashes it for you. Other endpoints require the already-hashed CID (hashed_cid, e.g. "0xabc...") — a keccak256 hex string you get back from list_actions. As a rule: creation endpoints (add_action, add_action_to_group) take the raw CID; update/delete endpoints (delete_action, remove_action_from_group, update_action_metadata) take the hashed CID.GET /list_api_keys?page_number&page_size— List usage API keys (paginated). Returns metadata only — key values are not returned.GET /list_groups?page_number&page_size— List groups.GET /list_wallets?page_number&page_size— List wallets (PKPs).GET /list_wallets_in_group?group_id&page_number&page_size— List wallets in a group (group_idis a u64).GET /list_actions?[group_id]&page_number&page_size— List actions. Whengroup_idis provided, lists actions in that group. When omitted, lists all actions on the account.GET /get_node_chain_config— Returns chain config, including contract addresses. No auth required.GET /get_api_payers— Returns the list of API payer addresses. No auth required.GET /get_admin_api_payer— Returns the admin payer address. No auth required.POST /get_lit_action_ipfs_id— Compute the IPFS CID for a given JS code string. Body is a JSON string. No auth required.
POST /remove_usage_api_key— Delete a usage key. Body:{"usage_api_key": "..."}.POST /update_usage_api_key— Update all permissions on an existing usage key. Body: same shape asadd_usage_api_key, plususage_api_key.POST /update_usage_api_key_metadata— Update only the name/description of a usage key. Body:{"usage_api_key": "...", "name": "...", "description": "..."}.POST /remove_group— Delete a group. Body:{"group_id": "..."}.POST /update_group— Update group name, description, and permitted PKP IDs / CID hashes. Body:{"group_id": 1, "name": "...", "description": "...", "pkp_ids_permitted": [], "cid_hashes_permitted": []}.POST /add_action— Register a standalone action (name + description + IPFS CID). Body:{"action_ipfs_cid": "Qm...", "name": "...", "description": "..."}.POST /delete_action— Delete an action and its metadata from the account. Body:{"hashed_cid": "0x..."}(already-hashed CID).POST /remove_action_from_group— Remove an IPFS action from a group. Body:{"group_id": 1, "hashed_cid": "0x..."}(already-hashed CID).POST /update_action_metadata— Update the name/description of a registered action. Body:{"hashed_cid": "0x...", "name": "...", "description": "..."}.POST /remove_pkp_from_group— Remove a PKP from a group. Body:{"group_id": 1, "pkp_id": "..."}.
Billing
GET /billing/stripe_config— Returns the Stripe publishable key. No auth required.GET /billing/balance— Returns the current credit balance for the authenticated account.POST /billing/create_payment_intent— Creates a Stripe PaymentIntent. Body:{"amount_cents": 500}(minimum 500 = $5.00). Returnsclient_secretfor use with Stripe.js.POST /billing/confirm_payment— Verifies a succeeded PaymentIntent and credits the account. Body:{"payment_intent_id": "pi_..."}.
ChainSecured-mode HTTP endpoints
Three HTTP endpoints back the ChainSecured (sovereign) flow. They sit alongside the on-chain writes — see API mode vs ChainSecured mode for the full SDK-side workflow and when to choose each mode. All three (and the billing-auth header described above) share the same EIP-712 typed-data envelope. The wallet UI displays a labelled struct —address and issuedAt fields under a stable (name: "Lit ChainSecured", version: "1", chainId) domain — so users can see exactly what they’re signing. The primaryType pins the signature to a specific flow and is part of the EIP-712 type hash, so a signature minted for one endpoint is rejected by every other endpoint at the digest level. Typed-data payloads longer than 4 KiB (serialised JSON) are rejected.
| Endpoint | primaryType |
|---|---|
/create_wallet_with_signature | CreateWallet |
/convert_to_chain_secured_account | ConvertAccount |
/add_usage_api_key_with_signature | AddUsageApiKey |
X-Wallet-Auth billing header | BillingAuth |
issuedAt as the only replay protection — no nonce store. Worst-case replay on the unauthenticated mint endpoints just produces an extra unattached PKP (compute cost only — see each endpoint below for specifics).
POST /create_wallet_with_signature
Mints a PKP via DStack MPC after verifying a wallet-ownership signature. Used by createWallet in ChainSecured mode; the response is then passed to the on-chain registerWalletDerivation call (signed by the same wallet) to register the PKP to the account.
No API key required. primaryType must be CreateWallet.
Request body:
derivation_path verbatim into registerWalletDerivation(adminHash, wallet_address, derivation_path, name, description) on the AccountConfig contract — until that lands, the PKP exists in MPC but is not registered to any account.
POST /convert_to_chain_secured_account
Flips a managed (API-mode) account to ChainSecured (unmanaged) in a single on-chain transaction. The account’s apiKeyHash is preserved — groups, PKPs, action metadata, and usage API keys (everything keyed by apiKeyHash on-chain) stay attached. Only the admin wallet and the managed flag change on-chain. Billing should be re-verified after conversion: Stripe credits are associated with the Stripe customer resolved from the current admin wallet address, so a credit balance is not guaranteed to carry over automatically when the admin wallet changes. There is no reverse path.
Requires the existing master API key (sent via X-Api-Key or Authorization: Bearer, per the auth header conventions above). The server’s api_payer signs the on-chain conversion after verifying the wallet signature; the new admin must sign EIP-712 typed data with primaryType: "ConvertAccount".
Request body:
client.convertToChainSecuredAccount), and the post-conversion verification checklist.
POST /add_usage_api_key_with_signature
The ChainSecured counterpart to /add_usage_api_key. Mirrors create_wallet_with_signature: the server mints a usage-key wallet via DStack MPC after verifying a wallet-ownership signature, then returns the secret (base64-encoded) plus the wallet address and derivation path. The client follows up on-chain — only the admin wallet of a ChainSecured account can call setUsageApiKey, so the server cannot complete the attach for you.
No API key required. primaryType must be AddUsageApiKey. Worst-case replay just returns a fresh secret for an unattached wallet — equivalent to a freshly generated keypair until the admin wallet calls the on-chain follow-ups, so compute cost only.
Request body:
registerWalletDerivation(adminHash, wallet_address, derivation_path, name, description)— registers the PKP to the account.setUsageApiKey(adminHash, keccak256(usage_api_key_bytes), expiration, balance, name, description, …permissions)— attaches the usage key with its permission set.
usage_api_key is just a freshly minted keypair with no on-chain identity.
Both request/response shapes and OpenAPI spec are available directly in the dev system. For a Swagger UI implementation of the OpenAPI spec, please browse to:
https://api.chipotle.litprotocol.com/core/v1/swagger-ui
Open API Specification
The OpenAPI spec itself can be found at:https://api.chipotle.litprotocol.com/core/v1/openapi.json Note that these specs are subject to minor changes and will always be available with the dev server endpoints.