Skip to main content

AI Agents

Lium is agent-first compute: the renter path — account, key, funding, rent, SSH, teardown — runs with no browser, no e-mail confirmation and no human click. This page is the entry point for AI agents (Claude, ChatGPT, Cursor, in-house copilots, …) integrating with Lium. Everything else in the Developers section also applies to agents — this page stitches the pieces together; Scripting for agents is the flag-by-flag contract for a script.

Prefer to work from a single file? lium.io/llms-full.txt is the whole agent reference in one fetch — install, signup, the agent skill, and every CLI and SDK command — enough to go from no account to a rented GPU without reading anything else.

Get started in 5 min​

The CLI is the preferred surface for an agent: it covers signup, funding, renting and SSH, so there is no web form to fill and no HTTP to hand-roll. Drop to the REST API only where the CLI cannot go — no shell in your sandbox, or an endpoint it does not wrap.

  1. Install the CLI and get an account:
    curl -fsSL https://lium.io/install.sh | bash
    export LIUM_API_KEY=sk_... # you already hold a key: nothing else to set up
    lium signup --email you@example.com # no account yet
    lium init --no-browser # account exists, no key — prints a URL a human approves
  2. Rent a GPU and connect:
    lium ls --format json # browse machines; pass the `id` field to up
    lium up <node-id> --yes --no-ssh --ttl 1h --name job-1 # rent, return when ready, self-remove in 1 h
    lium exec <pod> "nvidia-smi" # run without a terminal (lium ssh is interactive)
  3. Ground yourself in the docs — add the MCP server for targeted search:
    {
    "mcpServers": {
    "lium-docs": { "url": "https://docs.lium.io/mcp" }
    }
    }
    Or pull the whole corpus in one fetch: curl -sSL https://docs.lium.io/llms-full.txt.
  4. Call the REST API for anything the CLI does not cover:
    curl -sSL https://lium.io/api/openapi.json

Pick the right surface​

GoalUse thisWhy
Answer questions about Lium docsMCP endpoint — https://docs.lium.io/mcpTargeted search + page reads, no token bloat
Ground a long conversation in the full docsllms.txt / llms-full.txtOne fetch, every page concatenated
Read a single page as raw markdownAppend .md to any URL — e.g. /providers/quickstart.mdNo HTML to parse
Quote a GPU price with no accountPricing pages and price feed — https://lium.io/pricing.json, or Accept: text/markdown on /pricing and /gpu/<slug>One row per model with the live range; the pages answer in markdown
Answer what Lium is and who runs itAbout page — https://lium.io/aboutOne HTML page of plain facts (the company, billing, provider payouts, listed GPU classes, support), each linked to its source; no key
Call an endpoint the CLI does not wrapAPI — https://lium.io/api/openapi.jsonSource of truth for every REST endpoint
Drive pods from a shell agentCLIStable subcommands, JSON output, no auth headers to manage
Get an account with no human in the loopFingerprint signup — POST https://lium.io/api/auth/signupNo email or confirmation click; returns the login fingerprint and normally an API key
Take a user from no account to an API keylium signupCreates the account and mints its key from the terminal — no web form
Teach your agent Lium's commands onceAgent skill — npx skills add Datura-ai/lium-skill --skill liumShips with the agent, so no doc fetch mid-task
Automate the provider portallium providerSame surface as provider.lium.io: node lifecycle, central-miner-server config, sync, billing, machine requests — all --json-able
Write code against typed Python clientsSDKlium.machine decorator + Lium() client

Stable agent-facing URLs​

These URLs are stable and safe to hard-code in agent configurations:

https://docs.lium.io/mcp # docs MCP JSON-RPC endpoint
https://docs.lium.io/llms.txt # docs index + summaries
https://docs.lium.io/llms-full.txt # all docs concatenated
https://docs.lium.io/<any-page>.md # raw markdown for any page
https://lium.io/api/openapi.json # live platform OpenAPI 3.1 spec
https://lium.io/documents # Swagger UI for the same spec
https://lium.io/llms.txt # platform agent index: CLI + skill install
https://lium.io/llms-full.txt # full CLI/SDK reference, self-contained
https://lium.io/pricing.json # per-model GPU prices, JSON, no key
https://lium.io/pricing # pricing hub; Accept: text/markdown for the markdown twin
https://lium.io/gpu/<slug> # one page per GPU model, same negotiation
https://lium.io/api/public/v1/nodes # per-node inventory feed, no key
https://lium.io/about # company facts with sources, HTML only, no key

A wrong URL answers in markdown or JSON​

A path lium.io does not serve returns HTTP 404. This covers a page that does not exist and a GPU page for a model that does not exist. The body depends on the Accept header, and then on the client. A browser gets the HTML page with a search box and the links below. Any other client with no stated preference (curl, requests, Go's net/http, any User-Agent without Mozilla) gets a short markdown body:

curl -s https://lium.io/no/such/page
# 404: no page at `/no/such/page`

https://lium.io has no page at this path. Where to look instead:

- Sitemap (every public page): https://lium.io/sitemap.xml
- Agent index: https://lium.io/llms.txt
- Documentation: https://docs.lium.io
- API (OpenAPI): https://lium.io/api/openapi.json

Send `Accept: application/json` to get this error as JSON.

Send Accept: application/json to get the same error in the envelope the API uses (see Authentication → Error responses), with the same links as fields:

curl -s -H 'Accept: application/json' https://lium.io/no/such/page
{
"error": {
"code": "not_found",
"message": "No page at /no/such/page on this site.",
"hint": "Public pages are listed in https://lium.io/sitemap.xml and, for agents, https://lium.io/llms.txt; the API lives under https://lium.io/api (OpenAPI: https://lium.io/api/openapi.json) and the documentation at https://docs.lium.io."
},
"links": {
"docs": "https://docs.lium.io",
"llms_txt": "https://lium.io/llms.txt",
"api": "https://lium.io/api/openapi.json",
"sitemap": "https://lium.io/sitemap.xml"
}
}

The client's top-ranked Accept type wins: text/html, application/json or text/markdown. Only a tie (no header, or a bare */*) falls to the User-Agent. So a tool that sends Accept: text/html gets the HTML page, and a browser script that sends Accept: application/json gets the JSON. One exception: the GPU pages (/gpu/<slug>) are served as HTML and as markdown only. Accept: application/json there answers 406 with a markdown body that lists the agent resources, whether the model exists or not. A dead GPU slug still gets the markdown 404 above for a bare curl and for Accept: text/markdown. When the request carried an X-Request-Id header that looks like an id (up to 64 letters, digits, ., _ or -), the markdown ends with a Request id: line and the JSON has error.request_id. The response is Cache-Control: no-store. The provider portal (provider.lium.io) answers the same way. Its links are the provider docs, llms.txt, the provider API's OpenAPI document and the marketplace (links.docs, links.llms_txt, links.api, links.marketplace in the JSON).

Under /api the platform API answers its own 404s in the JSON envelope (with request_id, always), so a client can treat every JSON 404 from either origin the same way.

The usual guesses redirect (308) to the real path: /openapi.json, /swagger.json, /swagger/v1/swagger.json and /docs/openapi.json go to /api/openapi.json; /swagger to the Swagger UI at /documents; /docs to https://docs.lium.io/; /search?q=… to the marketplace, whose ?q= is its search parameter; a trailing slash (/pricing/) to the path without it.

Start from no account​

An agent creates the account itself — no web form. There are two paths, and the choice decides whether a human has to step in at all.

Fingerprint — fully autonomous​

One unauthenticated POST creates the account and returns its login fingerprint. It also returns an API key ready for the X-API-Key header when key minting succeeds; api_key is null when minting fails, without rolling back the account. No email address, mailbox or confirmation click is required.

curl -fsS -X POST https://lium.io/api/auth/signup \
-H "Content-Type: application/json" -d '{}'

Despite the name, a fingerprint is not a passkey, WebAuthn or biometrics — it is a random 32-character string, returned exactly once, that is both the dashboard login and the only way back into the account. Store it before you do anything else. Trade-offs: no password reset (lose the string and the account is gone) and no email notifications.

Full recipe, response fields and rate limits: Signing up without an email.

Email — needs a human once​

lium signup creates the account and stores its API key. Ask for the user's real email because the confirmation link, password resets and account messages go there. Email confirmation does not gate renting.

lium signup --email you@example.com --json

Either way, a new account gets a $5 credit when the signup passes Lium's abuse checks. Among them, a signup the risk score rates high risk gets no credit, Lium gives no second credit to an email address or a device that a credited account already used, and the credits are capped per network and per day; other checks apply too. An email signup gets it after the user clicks the confirmation link, within 14 days of signup. A fingerprint signup gets it once the account adds an email address (PUT /api/users/me with email and the fingerprint) and that link is clicked, within the same 14 days. Either way lium signup answers signup_credit_granted: false even when the $5 will land on that click. Read signup_credit_granted from the response, then check the balance before renting. The grant is once per new account; a retry does not add a second $5. An account created while the grant was off is not credited later. While part of the $5 is unspent, the account cannot send credit to another account, your own top-ups included. 14 days after the $5 lands, Lium takes back the unspent part, and transfers work again. With the $5 credit and no top-up, you can rent only nodes below $20 per hour.

Signup to running pod, end to end​

No browser step and no confirmed email anywhere in this path — the balance is the only gate. A positive balance is not sufficient: renting needs a balance above 15 minutes of the node's hourly price, that is hourly_price / 4. A $63.92 per hour node needs more than $15.98. A lower balance gets HTTP 403 with the required amount in the error text.

lium signup --email you@example.com --json # or POST /api/auth/signup for no email at all
lium balance --json # must exceed 15 min of the node's hourly price
lium ls --format json # pick a node
lium up <node-id> --yes --no-ssh --ttl 15m # rent it, return when ready, auto-terminate after 15m
lium exec <pod> "nvidia-smi" # run something on it
lium rm <pod> # hand it back

Authentication​

The platform API authenticates with an API key, sent in the X-API-Key header on every request; the CLI stores the key and sends it for you. An agent that already holds a key needs nothing else: export LIUM_API_KEY=sk_... and every lium command and the SDK use it (the environment wins over ~/.lium/config.ini). The human-once step is creating that key — at Access → API Keys on lium.io, or by POST /api/auth/signup, which returns one with the account. The docs surfaces (MCP, llms.txt, .md URLs) require no auth. API Authentication has the full reference — where the key is read from and in what order, how to verify it (lium balance --json or GET /users/me; lium ls succeeds with any key, right or wrong, and proves nothing), and the 401/403 error envelope.

lium signup mints and stores the key for a new account. For an account that already exists, lium init --no-browser prints an approval URL and a session ID; once the user has approved it, lium init --session <ID> saves the key. Plain lium init opens a browser; with no terminal it takes the --no-browser path and prints the URL and session ID. With a key in hand, export LIUM_API_KEY is the headless path. A key the user copies from Access → API Keys (lium.io/ssh-keys, then the API Keys tab) works too.

export LIUM_API_KEY=your_api_key_here
curl https://lium.io/api/pods -H "X-API-Key: $LIUM_API_KEY"

Self-funding (top up your own balance)​

An agent with its own crypto wallet can keep itself funded without a human. Use lium topup: create a stablecoin invoice, read the deposit address, send the funds from your wallet, then poll the balance. Every subcommand supports --json.

# 1. Create a $20 USDT (TRON) invoice; capture the address + exact amount
INVOICE=$(lium topup create -a 20 -c USDT -n tron --json)
ADDRESS=$(echo "$INVOICE" | jq -r .deposit_address)
AMOUNT=$(echo "$INVOICE" | jq -r .crypto_amount)

# 2. Send exactly $AMOUNT USDT on TRON to $ADDRESS from your own wallet.
# Lium never moves your funds — only you can sign this transfer.

# 3. Poll until the credit lands
lium balance --json

Lium issues the invoice and credits the balance once the payment is confirmed on-chain; the transfer itself stays in your wallet. See lium topup for currency discovery and the full invoice response.

With a saved card​

Once a card is saved on the account (the cardholder adds it with Add card on the Billing page; a one-time card payment there does not save the card), an API key holding the billing scope tops up from it with no browser:

curl -X POST https://lium.io/api/payments/topup -H "X-API-Key: <your billing-scoped API key>" \
-H 'Content-Type: application/json' -d '{"amount_usd": 20, "idempotency_key": "run-42"}'

A 202 processing answer with a payment_intent_id is usually credited within seconds, by the Stripe webhook; a 202 whose payment_intent_id is null means the charge outcome is not known yet (the charge may or may not have gone through), and the same webhook, or a repeat with the same key, settles it. Some top-ups need the cardholder to confirm with their bank first (3-D Secure): the answer is 402 CARD_AUTHENTICATION_REQUIRED with a next_action_url. Hand that URL to the cardholder; the balance is credited once they confirm, with no further call. Do not retry with a new idempotency_key meanwhile, since that would start a second payment. A repeat with the same key answers the same URL. The URL is good for 7 days: a confirmation after that is canceled with 402 CARD_AUTHENTICATION_EXPIRED and nothing is charged. Every top-up is charged only when the bank's 3-D Secure for that payment shifts the fraud liability to the bank (a card's earlier confirmation does not count): when 3-D Secure cannot run for the card, or the bank lets the payment through without it, the answer is a final 402 CARD_AUTHENTICATION_UNAVAILABLE and nothing is charged. A saved wallet (Link, Apple Pay, Google Pay) is refused before anything is sent to the bank with 402 WALLET_NOT_SUPPORTED: pass a saved card's payment_method_id, or set a card as the default.

  1. Install the CLI and authenticate — fingerprint signup (POST /api/auth/signup) for a new account with nobody to ask, lium signup when the user wants an email account, lium init --no-browser for an existing one.
  2. Drive the platform with lium commands, reading results as JSON.
  3. Drop to the REST API only where the CLI has no equivalent: resolve the endpoint from the OpenAPI spec and send X-API-Key.
  4. Pull context from MCP search — or feed llms-full.txt once — when the task is to explain or troubleshoot.
  • MCP endpoint — JSON-RPC contract and tool definitions
  • llms.txt — llmstxt.org-format docs bundle
  • API — the live OpenAPI spec, code-gen and tool-use examples
  • CLI overview — full command surface
  • SDK — typed Python client