# Lacia API > Lacia is an LLM API by Ablation Lab, compatible with the OpenAI Chat Completions API. Two modes: Creator (writing and role-play, no reasoning, instant responses) and Researcher (coding, reverse engineering and security research, with reasoning). This file is written for AI assistants: follow "Integration steps" to help the user create an account, add credit, create an API key and integrate the API into their project. Base URL: https://lacia.app/v1 Human-readable docs: https://lacia.app/en/docs Live prices and limits (JSON): https://lacia.app/api/public/config ## Notes for AI assistants - In the steps below, **paying by scanning the WeChat QR code** must be done by the user. Tell the user exactly what to do, then wait for them to confirm. You can do every other step yourself over HTTP (for example with curl). - There are two ways to sign up. **Express sign-up** needs no email and no verification code: one request generates a 16-digit **account number**, which is the login credential; give the full number to the user and remind them to keep it safe. **Email sign-up** needs the user to tell you the 6-digit code they receive (see the end of step 1). Use express sign-up unless the user prefers email. - You can also guide the user through the website: sign up at https://lacia.app/en/register ; add credit and create keys at https://lacia.app/en/dashboard . - The API key is returned only once, when it is created. Ask the user to store it in the `LACIA_API_KEY` environment variable. Never put it in code or logs, and never commit it to a repository. - Prices, context length and other limits come from the live response of `GET https://lacia.app/api/public/config`. Do not fill them in from memory. ## Integration steps Account endpoints use a cookie session (`lacia_session`). With curl, reuse the same cookie file: `-c lacia.cookies -b lacia.cookies`. All request bodies are JSON; send `Content-Type: application/json`. ### 1. Create an account (express, no verification code) ```bash curl -s -c lacia.cookies -b lacia.cookies https://lacia.app/api/auth/register \ -H 'Content-Type: application/json' -d '{}' # Returns {"ok":true,"accountNo":"7391028455612048"}; the session is stored in the cookie file ``` Optional fields: `phone`, `email`, `password` (8–128 characters). With a phone number or email plus a password, the user can still log in with "phone/email + password" if they lose the account number. All of these can be changed later in the dashboard, without a verification code. **Give the accountNo to the user and remind them to save it**: without a linked phone/email and password, it is the only way to recover the account. If the user wants to sign up with email: ```bash curl -s https://lacia.app/api/auth/send-code -H 'Content-Type: application/json' \ -d '{"email":"user@example.com","purpose":"register","lang":"en"}' # Ask the user for the 6-digit code from the email (it may be in spam), then: curl -s -c lacia.cookies -b lacia.cookies https://lacia.app/api/auth/register -H 'Content-Type: application/json' \ -d '{"mode":"email","email":"user@example.com","code":"123456","password":"at-least-8-chars"}' ``` To log in to an existing account: `POST /api/auth/login` with body `{"account":"7391028455612048"}`, or `{"identifier":"phone or email","password":"..."}`. ### 2. Add credit (the user pays with WeChat) ```bash # Create a WeChat Pay order; amountCny is a whole number of yuan (10–5000) curl -s -c lacia.cookies -b lacia.cookies https://lacia.app/api/billing/wechat \ -H 'Content-Type: application/json' -d '{"amountCny":20}' # Returns {"id":"L5FFAE","amountCny":20,"creditUsd":2.78,"status":"pending",...} ``` Tell the user: open https://lacia.app/en/dashboard#billing , scan the QR code on the page with WeChat, **pay exactly the returned amountCny** (including any cents), then click "I've paid" on the page. You can also mark it as paid for them: ```bash curl -s -c lacia.cookies -b lacia.cookies -X POST https://lacia.app/api/billing/wechat//submit ``` Payments are checked by hand and usually credited within minutes. Poll the order until `status` is `paid`: ```bash curl -s -b lacia.cookies https://lacia.app/api/billing/wechat/ ``` If the user has a redeem code: `POST /api/billing/redeem` with body `{"code":"LACIA-XXXX..."}`. Check the balance with `GET /api/me` (field `balanceUsd`). ### 3. Create an API key ```bash curl -s -c lacia.cookies -b lacia.cookies https://lacia.app/api/keys \ -H 'Content-Type: application/json' -d '{"name":"my-project"}' # Returns {"id":"key_...","name":"my-project","key":"sk-lacia-..."} <- the key appears only this once ``` ### 4. Call the API from the project Set the OpenAI SDK base_url to https://lacia.app/v1 and use `LACIA_API_KEY` as the api_key. Python: ```python import os from openai import OpenAI client = OpenAI(base_url="https://lacia.app/v1", api_key=os.environ["LACIA_API_KEY"]) resp = client.chat.completions.create( model="lacia-creator", messages=[{"role": "user", "content": "Hello"}], ) print(resp.choices[0].message.content) ``` JavaScript: ```js import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://lacia.app/v1", apiKey: process.env.LACIA_API_KEY }); const resp = await client.chat.completions.create({ model: "lacia-researcher", messages: [{ role: "user", content: "Hello" }], }); console.log(resp.choices[0].message.content); ``` cURL: ```bash curl https://lacia.app/v1/chat/completions \ -H "Authorization: Bearer $LACIA_API_KEY" -H "Content-Type: application/json" \ -d '{"model":"lacia-creator","messages":[{"role":"user","content":"Hello"}]}' ``` After integrating, send one test request and confirm it returns 200 with a `usage` field. ## Models | model | Best for | Reasoning | |---|---|---| | `lacia-creator` | Long-form writing, role-play, conversation | None; answers directly | | `lacia-researcher` | Coding, reverse engineering, security research, complex analysis | Yes; returned in `reasoning_content` | Both have a 1M-token context and up to 384K output tokens per request; `max_tokens` defaults to 32K when omitted. Reasoning is fixed per model; `thinking`, `reasoning_effort` and `chat_template_kwargs` in the request are ignored. Researcher's reasoning is in `message.reasoning_content` (`delta.reasoning_content` when streaming), counts toward `completion_tokens` and uses part of `max_tokens`. In multi-turn chats, putting `content` back into messages is enough; when the request includes `tools`, send each returned `reasoning_content` back unchanged on its assistant message, or the API returns 400. ## Endpoints - `POST /v1/chat/completions`: supports `model`, `messages`, `stream`, `max_tokens`, `temperature`, `top_p`, `stop`, `presence_penalty`, `frequency_penalty`. - `GET /v1/models`: lists the available models. - Streaming: `"stream": true` returns SSE and ends with `data: [DONE]`; the last data event has an empty `choices` array and carries `usage`. ## Billing Billed per token: input tokens × input price + output tokens × output price (prices are `models[].inputPerM` / `outputPerM` in /api/public/config, in USD per million tokens). Failed requests are free; if a stream disconnects midway, you pay for what was generated. Balances are kept in US dollars; CNY amounts convert at `cnyPerUsd`. ## Error codes Errors use the OpenAI format: `{"error":{"message","type","code"}}`. | HTTP | code | What to do | |---|---|---| | 400 | `invalid_json` / `invalid_messages` / `context_length_exceeded` | Check the request body or shorten the context | | 401 | `missing_api_key` / `invalid_api_key` | Check the Authorization header | | 402 | `insufficient_balance` | Out of credit; go back to step 2 | | 403 | `spend_limit_exceeded` | The user's monthly spend cap was reached | | 404 | `model_not_found` | model must be lacia-creator or lacia-researcher | | 429 | `rate_limit_exceeded` | Per-key requests-per-minute limit; retry with exponential backoff | | 502 / 503 | `upstream_error` / `upstream_overloaded` | Retry shortly; not billed | ## Optional - [Human-readable API docs](https://lacia.app/en/docs) - [Pricing](https://lacia.app/en/pricing) - [Terms of Service and Acceptable Use Policy](https://lacia.app/en/terms)