https://api.modulex.dev/workflows. This reference covers the base URL and how request URLs are composed, the no-/v1 and trailing-slash rules, and how ModuleX versions and deprecates the API.
This page is the API-reference companion to Base URLs, environments & versioning, which walks through pointing each SDK at a local or staging backend and the per-SDK environment-variable behavior. For the request lifecycle and content types, see the API overview; to authenticate requests, see Authentication.
Base URL
The API has one canonical production host. The SDKs default to it, so you do not set the base URL for normal use — you override it only to target a local backend or a self-hosted deployment.
Both the JavaScript SDK and the Python SDK hardcode
https://api.modulex.dev as the default base URL. The Python SDK additionally reads a MODULEX_BASE_URL environment variable as a fallback; the JavaScript SDK does not — see Switching environments for the full resolution order per SDK.
https://api.modulex.dev serves only REST endpoints and the run-event SSE streams. The ModuleX web app and the OAuth redirect target live at a separate host, https://app.modulex.dev, and realtime canvas collaboration runs over a separate Socket.io server. Do not point SDK calls at the app host. See Realtime overview and Credentials & OAuth2.How a request URL is built
The SDKs build every request URL asbaseUrl + path — the route path is appended verbatim, with no version segment inserted and no other rewriting. A trailing slash on the base URL is stripped before the path is joined, so https://api.modulex.dev/ and https://api.modulex.dev behave identically.
Request URL composition
No /v1 path segment
ModuleX does not put a version number in the URL path. There is no /v1, no /api/v1, and no /api prefix — each resource router mounts directly at its prefix.
Trailing slashes
Automatic trailing-slash redirects are turned off. A route is matched exactly as declared, so request the path without a trailing slash.
Always call the canonical path with no trailing slash. The SDKs already do this for you, so this only matters when you build request URLs by hand (for example, in cURL or a custom HTTP client).
Versioning
ModuleX versions the API and the SDKs separately. Neither uses a version segment in the URL path.API versioning
The API is unversioned in the URL. There is no/v1 path segment, and there is no API-version request header to send or pin — you cannot request a specific API version from the client side.
The backend application advertises an internal version string of 0.1.2, visible at the service root GET / and the public health endpoint GET /system/health. This is the build version of the service, not a contract version you negotiate against — it does not change how you call the API and you do not pass it on requests.
Because there is no version negotiation, ModuleX evolves the API in a backward-compatible way wherever possible: new fields are additive, and existing fields keep their meaning. Track changes that affect you through the changelog, and use the SDK ⇄ API parity matrix to confirm which routes a given SDK release covers.
Responses are snake_case JSON (for example
run_id, created_at, organization_ids). The JavaScript SDK accepts camelCase request parameters and converts them to snake_case on the wire, but does not convert responses — so JavaScript responses are snake_case too. The Python SDK is snake_case end to end. See the SDK ⇄ API parity matrix for the casing rules per SDK.SDK versioning (semantic versioning)
The official SDKs follow semantic versioning and ship at version 1.0.0.
Pin the SDK version in your dependency manifest so a major release does not change behavior under you. Breaking changes land in a new major version; consult the changelog before upgrading across a major boundary. Notable changes already shipped in the 1.0 line include the retirement of the organization
member role (invites accept only admin; see Roles & permissions), realtime SSE frames discriminating on a type key inside the JSON rather than a named event line (see SSE run streaming), and the removal of client-side billing helpers from the JavaScript SDK (the subscriptions resource is Python-SDK-only).
Deprecation
ModuleX does not version the API in the URL, so a removed or replaced capability is communicated through the response status and a pointer to its replacement, plus the changelog. There is noDeprecation or Sunset response header to watch for.
Removed endpoints return 410
When a capability is removed rather than changed, the route returns410 Gone with a detail message that names the replacement. The live example is the former “LLM mode” of the run endpoint: a single-node chat or knowledge Q&A submitted to POST /workflows/run with only an llm config (no workflow, workflow_id, or system_workflow) has been removed in favor of the agentic Assistant.
410 response — LLM mode removed from /workflows/run
410 is the FastAPI HTTPException shape — a string detail. It is not the billing DenialEnvelope, and the SDKs do not map 410 to a dedicated error class; it surfaces as the base ModulexError. For the full set of error shapes and which surface emits each, see Errors & status codes.
Deprecated aliases
Some routes are kept as deprecated aliases for backward compatibility rather than removed. For example, the support-request router is mounted canonically at/requests and also at the deprecated alias /support, so POST /support is equivalent to POST /requests. Prefer the canonical path; aliases may be removed in a future major release and are noted in the changelog.
Interactive API documentation
The running backend serves machine- and human-readable references at the base URL. Use these to inspect the live schema for the environment you are calling.
For the curated, language-tabbed reference and a live “Try it” playground inside these docs, browse the endpoint pages under API overview. To check live availability, see System status & health.
What does not change per environment
Switching environments changes only the base URL. Everything else about a request is identical across production and a local or self-hosted backend:1
Authentication scheme
Every request sends
Authorization: Bearer mx_live_…, and organization-scoped requests also send X-Organization-ID. Use a key that belongs to the environment you are calling. See Authentication.2
Route paths
The same paths with no
/v1 segment, called without a trailing slash.3
Error envelopes
The same shapes, including the billing
DenialEnvelope returned as 402 / 403 / 429 on the metered run, composer, assistant, and managed-knowledge surfaces. See Errors & status codes.4
Rate limiting
The same per-key, per-user, and per-organization limits and
429 responses. See Rate limiting.Next steps
Base URLs, environments & versioning
The getting-started walkthrough: point each SDK at local or staging, with per-SDK environment-variable behavior.
Authentication
The
Authorization: Bearer header and X-Organization-ID org context.API overview
The request lifecycle, content types, and how each operation is shown three ways.
Errors & status codes
The three error shapes, the billing
DenialEnvelope, and the 410 removed-endpoint case.