Skip to main content
This page is the reference for the objects you meet through the ModuleX API and SDKs: what each one is, the fields it returns, how the objects relate, and the identifier conventions you need to join them correctly. It describes the data model as it is exposed on the API — internal storage, indexing, and database tuning are out of scope.
Wire responses are snake_case JSON. The official SDKs convert between camelCase and snake_case at their own boundary, so a field shown here as edit_version surfaces as editVersion in the JavaScript SDK and stays edit_version in the Python SDK and raw REST. See /sdks/parity.

Entity map

Two objects sit at the centre of the model — the organization and the user. An organization is the tenant and billing unit; a user is a person. Every workflow, run, credential, knowledge base, chat, and wallet belongs to exactly one organization. Tenant isolation is enforced per request: you select the active organization with the X-Organization-ID header, and every response is scoped to it. See /security/org-context.

Core objects and how they relate

Conventions you must know first

Treat every ModuleX timestamp as UTC and normalize on your side. A timezone-aware value emits an offset on the wire; a naive one does not — so normalize rather than comparing the raw strings.
Free-form metadata surfaces under prefixed field names rather than a bare metadata key: doc_metadata on documents, chunk_metadata on chunks, and extra_metadata on wallet ledger entries and catalog entries.
A credential is referenced everywhere — in the API, the SDKs, and from a native knowledge base — by its credential_id, a unique UUID. Always join on credential_id.

Organizations, users, and access

object
The tenant and billing unit. Every managed-usage record, plan, wallet, workflow, and knowledge base is scoped to one organization. Selected per request by the X-Organization-ID header. See /concepts/organizations-roles.
object
The join between a user and an organization, carrying the user’s role.
The member role is retired (deprecated 2026-06-20). It is no longer a current first-class role: Composer, Assistant, Knowledge, and schedule operations require owner or admin. Treat only owner and admin as valid roles. See /security/roles-permissions.
object
An API key with the prefix mx_live_. The plaintext key is shown once at creation; afterwards only a hint is kept for display, and the key itself is never returned again.
Send the key as Authorization: Bearer mx_live_… together with X-Organization-ID. The backend also accepts X-API-KEY: mx_live_…. See /api-reference/authentication.

Workflows

A workflow is the editable graph — nodes, edges, and run state. A run is one execution of a workflow. The two are distinct objects; see /concepts/workflows-and-runs for the conceptual model and /concepts/workflow-engine for how the graph executes.
object
The durable, editable workflow record.

The workflow_schema object

workflow_schema holds the complete workflow definition. The name, description, version, and tags fields above mirror values inside workflow_schema.metadata; the schema is the source of truth.
object
The nine node types are llm, tool, agent, function, conditional, interrupt, transformer, guardrails, and knowledge. Nodes reference earlier results with the template syntax {{nodeId.path}}. See /workflow-builder/nodes/overview and /workflow-builder/variables-and-references.
workflow_schema round-trips a fixed set of fields. When the realtime co-editing server saves, it keeps a fixed set of top-level fields — metadata, config, state_schema, nodes, edges, entry_point, input_parameters, end_points, start_position — and does not persist top-level keys outside that set. Do not assume an arbitrary key you add at the top level of workflow_schema will survive a reload. See /workflow-builder/realtime-coediting.

Edit history and the two version planes

Every edit is recorded, and there are two different counters both called “version”.
object
One append-only record per accepted flush of edits.
Two planes, both called “version”. During live editing the realtime room keeps an in-memory counter that increments once per accepted client operation. The persisted edit_version increments once per flush, and a single flush carries many operations. So after N operations and one flush, the in-memory counter has advanced by N while the persisted edit_version has advanced by 1. Clients see the in-memory plane through live acknowledgements and the persisted plane through the saved record — do not copy one over the other. See /workflow-builder/versioning-history and /realtime/presence-locks.
object
An immutable snapshot of a workflow taken at deploy time. A run can be tied to the deployment it was launched from.

Runs

object
The durable system-of-record for every real run. This is the object you query for run history and status.
Schedules add two more objects. A schedule defines a recurring trigger (schedule_type is interval or cron), and each fire produces a schedule-run record carrying its own id, run_id, status, and timing. See /workflow-builder/execution/schedule and /guides/schedule-a-workflow.

Identifiers and the three run-id identities

The single most important identity hazard in ModuleX: the word “run id” refers to different things at different layers. A reader must not assume one identity.
string
The identifier used for SSE streaming and run status of one execution. For agentic surfaces (Composer and Assistant), a new run_id is minted on every resume — the chat keeps the same thread_id, but each turn or resume has its own run_id. So this run_id is not stable across a conversation.
string
The conversation/checkpoint thread. For chat-backed agents, thread_id equals the chat’s id and is stable across the whole conversation.
string
The durable run identifier — the unique run_id on the run record. A resume reuses the same run_id (the record is updated in place). This is the stable, unique identifier the docs reference when they say “a run”.
Idempotency-Key does not de-duplicate runs. The SDKs send the header, but ModuleX assigns its own run_id per execution and does not use the header for run dedup. Sending the same Idempotency-Key twice will start two runs. See /sdks/errors-retries.

Credentials

A credential is a stored, encrypted authentication record linking an organization to an integration. See /concepts/credentials-oauth, /integrations/authentication, and /integrations/managing-credentials.
object
The credential’s secret material is not returned by the API — it is stored encrypted at rest and only decrypted server-side at execution. See /security/data-encryption for how that protection works.
The auth_type value you receive is one of six variants — oauth2, bearer_token, api_key, modulex_key, custom, internal. Author new credentials against this set. See /integrations/building/manifest-schema.

Managed-key credentials are indirected

A modulex_key credential does not expose a provider API key. You reference the credential, and ModuleX resolves the underlying managed key on your behalf, runs it, and meters the usage. This is how ModuleX-managed (non-BYOK) usage is billed in credits. See /billing/credits.

Knowledge

A knowledge base is the unit retrieval-augmented generation searches over. It holds documents, which are split into chunks, which carry vector embeddings. See /concepts/knowledge-rag, /platform/knowledge/overview, and /platform/knowledge/managed.
object
object
An uploaded file in a knowledge base.
object
A text segment of a document with its vector embedding.
The advertised “50MB” knowledge upload limit is not the enforced cap. The real upload cap is a plan entitlement that varies by plan. See /platform/knowledge/documents and /billing/usage-gating.

Billing, credits, and the wallet

Managed usage is priced in credits (100 credits = 1.00;1credit=1.00; 1 credit = 0.01). Each organization gets a monthly credit allowance from its plan; when the allowance is exhausted, a paid org with overage enabled spends down a prepaid wallet. See /billing/overview, /billing/credits, and /billing/wallet.
object
The prepaid balance an org spends after its plan allowance is gone. There is exactly one wallet per organization.
object
An append-only entry recording one wallet movement.
object
An append-only record of one managed-usage charge in credits.
The plan catalog, the active subscription (with its subscription_status and an operations_suspended flag), and Stripe billing records round out the billing model. The subscriptions resource is Python-SDK-only — there is no JavaScript equivalent. See /billing/subscription-lifecycle and /sdks/parity.

What happens when you delete an object

Deletion behavior is the part that surprises people, so it is worth stating explicitly.

Deleting an organization

Removes all of its data — members, credentials, workflows, runs, chats, knowledge bases, and the wallet with its ledger.

Deleting a user

History is preserved. A run, workflow, or chat the user created keeps existing, with the creator link cleared.

Blocked deletes

A user who still owns credentials or uploaded documents cannot be deleted until those are removed first.

Append-only and system-managed objects

Some records are append-only history and never change in place — wallet ledger entries, credit-usage records, workflow edit history, and run records. Treat them as immutable history. Others are system-managed and should not be treated as durable user data: the integration catalog and the node-type builder metadata are regenerated on each deploy. By contrast, runs, the wallet ledger, and credit-usage records are durable systems-of-record and are never reset.

Things to get right

1

Reference credentials by credential_id

A credential is referenced everywhere — including from a native knowledge base — by its credential_id.
2

Persist the durable run_id

Of the three run identities, only the durable run_id is stable and unique across a run’s lifecycle. Per-execution run ids change on every resume.
3

Treat owner and admin as the only roles

The member role is retired. Anything that requires a writer requires owner or admin.
4

Expect snake_case on the wire and prefixed metadata fields

Raw API responses are snake_case; free-form metadata surfaces under names like doc_metadata, chunk_metadata, and extra_metadata.
5

Do not rely on Idempotency-Key to de-dup runs

The header is accepted but ignored for run dedup; ModuleX assigns its own run_id.

Workflows & runs

The conceptual model behind the workflow and run objects, including the run lifecycle.

Workflow engine & nodes

How the workflow_schema, nodes, edges, and run state execute.

Credentials & OAuth2

How credentials are stored, resolved, and encrypted.

Errors & status codes

The error-envelope shapes you get back when an operation is denied or fails.