Skip to documentation
Lattice

Lattice / Developer manual

API documentation

Connect your application or coding tool to an OpenAI-compatible API. Start with a saved key, your account's Base URL and an explicitly chosen model.

01

Make your first request

  1. New here? Check closed beta enrollment. When enrollment is open, join with a single-use beta access code from your inviter; a valid code does not bypass paused enrollment. Existing accounts sign in and complete the current account consent. Open Account → API keys, name a key for your tool and save its secret when displayed. Your beta code enrolls an account; it is separate from your API key and paid access.
  2. Copy the Base URL from Account. It already includes /v1; append /models or /chat/completions once.
  3. For Go, copy the exact qualified model ID shown in Billing. Confirm that ID appears in authenticated GET /v1/models. A key alone does not grant model access.
bash
# Bash: replace all three placeholders before running a request.
# Copy the Base URL from Account → API keys; it already ends in /v1.
export LATTICE_BASE_URL='https://chat.lewd.win/v1'
export LATTICE_API_KEY='YOUR_SAVED_API_KEY'
export LATTICE_MODEL_ID='EXACT_MODEL_ID_FROM_BILLING'

Credentials and model IDs above are placeholders. Verify the host against Account, then set the values in a trusted local terminal or server environment. These examples do not make requests from this page.

Bash with curl and jq

Run the catalog check, then one generation. The example stops if your chosen ID is absent and uses jq to encode JSON safely.

bash
# Requires curl and jq. Copy Base URL from Account → API keys.
# LATTICE_BASE_URL includes /v1. Set your key and exact model ID.
set -euo pipefail
: "$LATTICE_BASE_URL" "$LATTICE_API_KEY" "$LATTICE_MODEL_ID"
curl --fail --silent --show-error "$LATTICE_BASE_URL/models" \
  -H "Authorization: Bearer $LATTICE_API_KEY" |
  jq -e --arg model "$LATTICE_MODEL_ID" '.data | any(.id == $model)' >/dev/null
curl --fail --show-error "$LATTICE_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $LATTICE_API_KEY" \
  -H "Content-Type: application/json" \
  --data "$(jq -nc --arg model "$LATTICE_MODEL_ID" \
    '{model:$model,messages:[{role:"user",content:"Hello"}]}')"

This shared quickstart uses curl's --fail, which can omit the error body. The Python example below reads the error JSON. Neither example retries a generation automatically.

Python without an SDK

Use the same environment variables. Save this as first_request.py and run python3 first_request.py (or python first_request.py on Windows). It prints the completion envelope and handles HTTP errors explicitly.

first_request.pypython
# Save as first_request.py. Requires Python 3; no SDK installation.
import json
import os
import sys
from urllib.error import HTTPError, URLError
from urllib.parse import urlsplit
from urllib.request import Request, urlopen

base = os.environ["LATTICE_BASE_URL"].rstrip("/")
key = os.environ["LATTICE_API_KEY"]
model = os.environ["LATTICE_MODEL_ID"]
url = urlsplit(base)
if (url.scheme != "https" or not url.hostname or url.username or url.password
        or not url.path.endswith("/v1") or url.query or url.fragment):
    sys.exit("Use the HTTPS Base URL copied from Account, including /v1.")

def request_json(path, payload=None):
    headers = {"Authorization": "Bearer " + key}
    data = None
    if payload is not None:
        headers["Content-Type"] = "application/json"
        data = json.dumps(payload).encode("utf-8")
    request = Request(base + path, data=data, headers=headers)
    try:
        with urlopen(request, timeout=300) as response:
            result = json.load(response)
            request_id = response.headers.get("x-lattice-request-id")
            if request_id:
                print("Request ID:", request_id, file=sys.stderr)
            return result
    except HTTPError as error:
        body = error.read().decode("utf-8", errors="replace")
        try:
            parsed = json.loads(body)
            detail = parsed.get("error", {})
            code = detail.get("code", "unknown") if isinstance(detail, dict) else detail
        except (ValueError, AttributeError):
            code = "unknown"
        print("HTTP", error.code, "error code:", code, file=sys.stderr)
        print("Request ID:", error.headers.get("x-lattice-request-id", "unavailable"),
              file=sys.stderr)
        retry_after = error.headers.get("Retry-After")
        if retry_after:
            print("Retry-After:", retry_after, file=sys.stderr)
        print(body, file=sys.stderr)
        sys.exit("Stopped. Review the error and Billing before another generation.")
    except (URLError, TimeoutError, OSError, ValueError) as error:
        print(type(error).__name__, file=sys.stderr)
        sys.exit("Outcome may be uncertain. Do not automatically repeat a generation.")

catalog = request_json("/models")
if not any(item.get("id") == model for item in catalog.get("data", [])):
    sys.exit("Exact model is absent from the catalog. Check Billing and availability.")

# One generation only. json.dumps safely encodes model IDs and prompt text.
result = request_json("/chat/completions", {
    "model": model,
    "messages": [{"role": "user", "content": "Say hello in one sentence."}],
    "max_completion_tokens": 128,
    "stream": False,
})
print(json.dumps(result, ensure_ascii=False, indent=2))

A timeout or disconnected response may follow billable dispatch. Check Billing and usage before choosing whether to send another generation; repeating a POST is a new request.

02

Endpoints and response shapes

Send Authorization: Bearer YOUR_API_KEY on every endpoint. Chat requests use Content-Type: application/json. Paths below include /v1; the examples append only the suffix to your copied Base URL.

GET/v1/models

Discover model IDs available to your credential. Returns object: list and a data array of model objects. Verify the exact Billing model ID; never choose the first entry automatically.

POST/v1/chat/completions

Send model and messages as JSON. Returns an OpenAI-compatible completion envelope, or SSE when stream is true. Function tools depend on the selected model’s capabilities.

GET/v1/usage

Read your account’s usage. Commercial accounts receive a ledger snapshot when commercial mode is configured; other accounts receive the legacy weekly activity summary described below.

Chat completions

Required fields are model and a nonempty messages array. Set max_completion_tokens to bound output. If you also send max_tokens, both limits must agree for commercial requests. The default is a nonstreaming response.

Read generated text from choices[].message.content, tool calls from choices[].message.tool_calls, and token counts from usage when provided. Model-specific fields can vary. Function tools require model support; your client executes the tools and supplies the resulting tool messages.

Commercial Go includes text chat and supported function tools. Vision, embeddings, audio, refinement endpoints and external provider overflow are outside that offer. The reserved lattice_marketplace request policy is rejected with unsupported_request_policy; it does not imply paid routing.

Account usage

bash
curl --fail-with-body --silent --show-error "$LATTICE_BASE_URL/usage" \
  -H "Authorization: Bearer $LATTICE_API_KEY"

For ordinary users, /v1/usage returns the commercial snapshot when commercial mode is configured, including when serving is paused. Otherwise, and for admins, it returns the legacy weekly summary. Detect the shape instead of assuming every response is a wallet.

enabled, model, computedAt
Commercial availability, configured model ID and snapshot timestamp. A listed model or a nonzero balance alone does not grant access.
entitlement, capabilities
Verified subscription state and current included/PAYG eligibility. A capability is a snapshot, not a reservation for your next request.
policy, concurrency
Current policy version, per-token reference rates and account-wide active/maximum requests. All keys share these limits.
windows.fiveHours / sevenDays / thirtyDays
Each window contains limit, used, reserved, uncertain, remaining and nextResetAt. Amounts use integer nanoUSD reference units: divide by 1,000,000,000 for virtual reference dollars, not spendable cash.
outputSafety
The same window fields measured in generated tokens, for the additional rolling output guard.
wallet
PAYG permission and cash balance, reserved, uncertain, available and liability amounts in nanoUSD, plus held. Divide cash amounts by 1,000,000,000 for actual dollars.
reconciliationRequired
Final usage is uncertain. Dispatched holds remain counted until reconciled; a rolling window boundary does not release them.

The legacy shape contains tier, policy, weekly, limits and window. Its weekly activity includes requests and token counts by modality, stream time and routing telemetry. It is recorded activity, not the commercial cash ledger. Billing is the authority for current entitlement, balances and availability.

03

Stream a completion

Set stream: true for Server-Sent Events (SSE). The example uses a recent curl with --fail-with-body to retain HTTP error JSON and --no-buffer to display incoming bytes. Curl displays the raw stream; it does not parse or validate SSE.

bash
# Bash: requires curl and jq; use the environment variables above.
set -euo pipefail
: "$LATTICE_BASE_URL" "$LATTICE_API_KEY" "$LATTICE_MODEL_ID"
curl --fail --silent --show-error "$LATTICE_BASE_URL/models" \
  -H "Authorization: Bearer $LATTICE_API_KEY" |
  jq -e --arg model "$LATTICE_MODEL_ID" '.data | any(.id == $model)' >/dev/null

# One POST. --no-buffer displays raw SSE as it arrives; curl does not parse it.
curl --no-buffer --fail-with-body --show-error \
  "$LATTICE_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $LATTICE_API_KEY" \
  -H "Content-Type: application/json" \
  --data "$(jq -nc --arg model "$LATTICE_MODEL_ID" \
    '{model:$model,messages:[{role:"user",content:"Say hello."}],
      max_completion_tokens:128,stream:true,
      stream_options:{include_usage:true}}')"

An application should parse SSE events across arbitrary network chunks, decode JSON data: values, read choices[].delta and handle error events. data: [DONE] is the terminal marker, not JSON. Do not treat each network read as a complete event.

Commercial streaming requests include final usage. Settlement requires a valid final usage chunk with an empty choices array, followed by [DONE] and a clean end of stream. A progress meter, partial text or [DONE] alone does not establish final usage.

If a dispatched stream is cancelled, interrupted or lacks a trusted final meter, its reservation remains counted as uncertain usage until reconciliation. Client token estimates and claimed cache hits do not settle the ledger. Review Billing before repeating the request.

04

Allowance and billing

Go launch target · $10/month

Paid launch remains disabled pending qualification. Billing shows actual purchase and serving availability for your account. Model identity, long context and project-cache retention targets are not availability or cache guarantees.

Included allowance uses virtual reference dollars: $4 per rolling 5 hours, $20 per rolling 7 days and $40 per rolling 30 days. All three windows apply. These are usage credits, separate from purchased cash.

Fresh input
$0.15 / million
Verified cached input
$0.03 / million
Generated output
$0.50 / million

These weights measure included virtual usage. The separate PAYG wallet displays actual cash prices before spending permission; the selected launch cash rate card uses the same numeric token rates. Matching numbers do not make virtual allowance redeemable cash.

The published included policy also has an 8M generated-token guard per rolling 30 days and one premium request at a time across all your keys. Operators can increase limits; Billing displays the current policy. Payment dates do not reset rolling usage.

Before dispatch, the server reserves a conservative input and output budget, including possible input up to the configured context bound. A small prompt can therefore require more available allowance than its eventual settled cost. Reduce the output limit for later requests where appropriate. Settled usage ages out gradually; nextResetAt is the next settled usage leaving a window, not a promise that every hold clears then.

Explicit PAYG permission

Requests without a billing-mode header use included allowance. They never fall back to cash. To spend purchased PAYG cash when qualified serving is available, enable Authorize prepaid API spend in Billing and add x-lattice-billing-mode: payg to each intended request. included is also an accepted explicit mode.

Account permission alone sends no request and buys no cash. Automatic top-ups are off. A paid request uses the configured qualified model; it does not select arbitrary marketplace or external providers. A failed purchase or return from checkout does not establish entitlement or credit.

Review allowance and spending state
05

Errors and recovery

Read the HTTP status and JSON error.code, plus error.message where provided. Preserve x-lattice-request-id when returned. Some errors occur before a request ID exists. Retry-After is supplied on some quota and upstream failures; honor it when present.

400
invalid_requestinvalid_billing_modecommercial_model_requiredconflicting_output_limitsoutput_limit_exceededcommercial_text_onlyunsupported_request_policy

Correct the JSON, billing header, exact model or output limit. Send text for Go. The reserved lattice_marketplace request field is rejected; it does not authorize paid provider routing.

401
invalid_api_key

Check the Bearer header and saved key. Create a new key if the original was revoked or lost.

402
commercial_entitlement_requiredcommercial_wallet_insufficientcommercial_account_hold

Review Billing for active entitlement, available cash or a hold. Included allowance never switches to cash automatically. A hold can require reconciliation or support.

403
legal_consent_requiredcommercial_payg_not_enabledcommercial_live_customer_requiredcommercial_endpoint_not_included

Complete current account consent or review Billing access. PAYG requires account permission. Embeddings, audio and refinements are outside the commercial Go offer.

404 / 413
model_not_foundrequest_too_large

Refresh the catalog for an unavailable model. Reduce an oversized request; ordinary chat requests have a 2,000,000-byte body limit and at most 128 messages and 64 function tools.

429
commercial_concurrency_limitcommercial_allowance_exhaustedcommercial_output_safety_limitburstconcurrencymodality_requestsweekly_hours

Wait for active work or rolling usage to clear, or reduce the next output limit. Honor Retry-After when supplied; commercial admission errors do not currently supply that header. Check Billing for reservations and uncertain usage.

502
upstream_unavailableupstream_errorinvalid_upstream_response

An upstream failure can follow dispatch. Preserve the request ID and check usage before deciding whether to send another generation.

503
commercial_not_qualifiedcommercial_disabledcommercial_ledger_unavailablemodel_not_readyquota_unavailableupstream_error

Serving, model readiness or accounting is unavailable. Check Billing and the catalog. Do not substitute a different paid model or retry an uncertain generation blindly.

Codes above cover common paths, not every model or legacy feature. A generation failure or lost response does not prove zero usage. Do not blindly retry a possibly dispatched POST, change to PAYG, or switch models. Check the recorded state first and retain the request ID for support. Never include your API key in a support message.

06

Keys, context and data handling

Keep API keys on a trusted server or local client, outside browser bundles, source control and shared logs. Save the secret when created. If a key is lost or exposed, revoke it in Account and create a replacement; deleting it from a local file does not revoke it.

API clients own conversation context. Send the messages needed for each request and apply your own storage policy. An API request is not saved as browser conversation history by this chat-completions route; usage metadata is recorded for accounting and operations.

Active prompts, tool inputs and responses are readable to the Lattice server and selected inference host/runtime. Transport encryption and browser history encryption do not conceal active inference from those hosts. Runtime prompt/KV state may remain after a request. A no-store response header does not establish cache erasure or a retention guarantee.

Review the Privacy Notice for processing, retention and privacy contacts, and the Terms and Acceptable Use Policy before connecting your application. Customer access is through the API. Browser chat and related inference tools are available to admins; owner-selected accounts may receive temporary access during the noncommercial beta. Buying Go does not unlock browser tools.