CLI tool and code examples for the LexSelect External API.
Server-to-server API. Keys (prefixed
lxs_) must not be embedded in browser applications, and cross-origin browser requests are not supported — a preflightOPTIONSreturns401by design.
- Get an API key from the Developer Portal
- Copy
.env.exampleto.envand add your key - Build the CLI or run an example
cd cli && go build -o lexselect .
./lexselect upload contract.pdfAll endpoints live under the base URL (https://api.lexselect.io/api) and require
Authorization: Bearer lxs_... with ProcessingAPI scope. Full, interactive
reference: the API docs.
| Method | Path | Description | CLI command |
|---|---|---|---|
POST |
/documents/upload |
Upload a file in one multipart request | upload |
GET |
/documents |
List files/folders within a parent (paginated) | list |
GET |
/documents/{id} |
Get a document's metadata | get |
DELETE |
/documents/{id} |
Soft-delete a document or folder | delete |
GET |
/documents/{id}/processing/latest |
Get the latest processing status | status |
GET |
/documents/{id}/processing/latest/pages |
List page metadata | pages |
GET |
/documents/{id}/parse |
Get the parsed structure (tree, kvps, text, tables, blocks) | parse |
GET |
/documents/{id}/render |
Render to Markdown/HTML (experimental) | render |
On the latest API version (2026-06-07), GET /documents/{id}/processing/latest
reports progress as facts — counts per scope — instead of a computed fraction:
{
"status": "in_progress",
"stage": "page-processing",
"pages_done": 7,
"pages_total": 12,
"total_known": true,
"progress_details": [
{"scope": "page", "kind": "page", "done": 7, "total": 12, "total_known": true}
]
}When total_known is false, the total may still grow — render counts honestly
(e.g. 7/12+) and do not derive a percentage. Pinning X-API-Version: 2026-03-06
keeps the legacy shape (processing_progress float + page_count). Note that the
/parse endpoint's page_count/total_pages are response-batch metadata and are
unchanged across versions.
Upload a document in a single request: POST /documents/upload with a
multipart/form-data body containing name, size, and the file part (put
name before file). The server stores the bytes, verifies the hash, and
triggers processing, returning the created document. Optionally pass parent_id
(defaults to your Default Project) and content_type (inferred from the file
name otherwise).
Every response (success or error) carries an X-Request-Id header for tracing. Errors are
RFC 9457 application/problem+json with the shape
{ type, title, status, detail }. Note: limit outside 1–100 returns 400 (it is not
clamped), and oversized request bodies return 413 problem+json.
Minimal, self-contained examples for learning the API.
| Example | Language | Description |
|---|---|---|
| upload-and-poll.ts | TypeScript | Single file: upload → poll → fetch the parsed result |
| sync-polling.ipynb | Python | Notebook: upload → poll → pages → parse → render |
| Variable / Flag | Description | Default |
|---|---|---|
LEXSELECT_API_KEY / --api-key |
Your API key (starts with lxs_) |
— |
LEXSELECT_API_URL / --api-url |
API base URL | https://api.lexselect.io/api |
The CLI looks for a .env in the working directory and walks up to parent directories,
so a repo-root .env is picked up even when you run the binary from cli/.
If you point the tools at a local stack whose S3 (LocalStack) serves a self-signed
certificate, a client that doesn't trust it will fail the presigned PUT. For the
TypeScript example, run with NODE_TLS_REJECT_UNAUTHORIZED=0 (local testing only).
- API Documentation — Interactive API reference
- OpenAPI Spec — Machine-readable spec