Skip to Content
DocumentationDevelopersRuntime API Reference

Momen Runtime API Reference

This document describes the runtime GraphQL API structure for Momen projects. Use it when debugging, integrating external systems, building code components, or connecting custom frontends.

Momen exposes a single GraphQL endpoint. Database access, Actionflow invocation, AI Agent sessions, and external API calls are expressed as query, mutation, or subscription operations with different root fields, arguments, and return shapes.

API endpoints

HTTP GraphQL

https://villa.momen.app/zero/{projectExId}/api/graphql-v2
ParameterDescription
projectExIdUnique identifier of your Momen project

Request body uses standard GraphQL JSON:

{ "query": "mutation CreateBlog($object: blog_insert_input!) { insert_blog_one(object: $object) { id } }", "operationName": "CreateBlog", "variables": { "object": { "title": "My first post" } } }

WebSocket subscription

wss://villa.momen.app/zero/{projectExId}/api/graphql-subscription

Subscriptions are used for async Actionflow tasks, streaming AI results, and live data updates.

Authentication

Pass JWT in the Authorization header:

Authorization: Bearer <jwt>

Without a JWT, requests run as anonymous/guest. With a JWT, the backend resolves account, roles, and permissions before database, Actionflow, AI, or external API execution.

Obtain JWT via login. Username/password example:

mutation AuthenticateWithUsername($username: String!, $password: String!, $register: Boolean!) { authenticateWithUsername(username: $username, password: $password, register: $register) { account { id permissionRoles } jwt { token } } }

register: true registers and logs in; false logs in only. Use jwt.token as the Bearer token.

Request and response shape

GraphQL operations are query, mutation, or subscription.

See the GraphQL documentation for general GraphQL concepts.

TypePurposeTypical Momen use
queryRead dataTable queries, async task status, read-only external APIs
mutationWrite or triggerCRUD, Actionflows, AI session create/send, external APIs
subscriptionListen for changesDB changes, Actionflow async results, AI streaming

Success returns data. Errors return an errors array:

{ "data": null, "errors": [ { "message": "permission denied", "path": ["insert_blog_one"] } ] }

Only requested fields are returned. For writes, id is available for downstream references.

Database operations

Momen generates GraphQL fields from your data model. Examples use table names blog, goods, order.

Field type mapping

Momen typeGraphQL typeNotes
TextStringText
Big integerbigintOften used for ids
DecimalDecimalHigh-precision numbers
BooleanBooleantrue / false
JSONBjsonbJSON object
DateTime (with timezone)timestamptzDate and time
Time (with timezone)timetzTime of day
DatedateCalendar date
Geo pointgeographyLocation
ImageFZ_ImageImage asset
VideoFZ_VideoVideo asset
FileFZ_FileFile asset

Media fields in inputs use resource ids: {field_name}_id for single assets, {field_name}_ids for arrays (e.g. cover_image_id).

Query data

Use query operations.

Root fields and parameters

The root field is the top-level entry (e.g. blog for the blog table):

query { blog(where: {...}, limit: 10) { id title } }
Field patternDescription
{table_name}List query with where, order_by, limit, offset
{table_name}_by_pkSingle row by primary key
{table_name}_aggregateAggregation with nodes and aggregate
{table_name}_group_byGroup by with having, where, order_by, etc.
fz_{table_name}_by_{column_name}Geo distance queries

Common parameters

ParameterDescription
whereFilter ({table_name}_bool_exp)
order_bySort (field, relation, aggregate)
distinct_onDistinct on columns
limitMax rows
offsetSkip rows (pagination)

where filter syntax

Logical operators

OperatorMeaning
_andAll conditions
_orAny condition
_notNegation

Comparison operators

OperatorMeaning
_eq / _neqEqual / not equal
_gt / _gteGreater / greater or equal
_lt / _lteLess / less or equal
_in / _ninIn set / not in set
_like / _ilikePattern / case-insensitive pattern
_is_nullNull check

Relation filters nest along relations:

{ "where": { "author": { "name": { "_eq": "Alex" } } } }

Operator-first syntax

For expressions like EXTRACT(MONTH FROM created_at) = 12, use operator-first form: operator first, left_operand (functions/columns), right_operand (literal).

Query:

query QueryAccountList($where: account_bool_exp) { account(where: $where) { id username created_at } }

Variables:

{ "where": { "_eq": { "bigint_operand": { "left_operand": { "extract_timestamptz": { "time": { "column": "created_at" }, "unit": "MONTH" } }, "right_operand": { "literal": "12" } } } } }

Query examples

List

query QueryBlogList($where: blog_bool_exp, $limit: Int, $offset: Int) { blog(where: $where, order_by: { id: desc }, limit: $limit, offset: $offset) { id title author_id } }
{ "where": { "_and": [ { "author_id": { "_eq": 10001 } }, { "title": { "_ilike": "%Momen%" } } ] }, "limit": 20, "offset": 0 }

By primary key

query QueryBlogByPk($id: bigint!) { blog_by_pk(id: $id) { id title content } }

Aggregate

query QueryBlogAggregate($where: blog_bool_exp) { blog_aggregate(where: $where) { nodes { id title } aggregate { count max { id } } } }

Insert data

Use mutation.

Field patternDescription
insert_{table_name}_oneSingle insert
insert_{table_name}Batch insert
ParameterDescription
objectSingle row
objectsMultiple rows
on_conflictUpsert / conflict policy

Single insert

mutation($object: blog_insert_input!, $on_conflict: blog_on_conflict!) { insert_blog_one(object: $object, on_conflict: $on_conflict) { id } }
{ "object": { "title": "My first post", "content": "Post body.", "author_id": 10001 }, "on_conflict": { "constraint": "unique_title", "update_columns": [] } }

Empty update_columns skips on conflict; listing all columns updates the existing row.

Batch insert

mutation( $objects: [blog_insert_input!]!, $on_conflict: blog_on_conflict! ) { insert_blog(objects: $objects, on_conflict: $on_conflict) { returning { id } } }

Update data

Field patternDescription
update_{table_name}Conditional batch update
update_{table_name}_by_pkUpdate by primary key
ParameterDescription
whereBatch filter
pk_columnsPrimary key for single-row update
_setSet field values
_incAtomic increment/decrement

Batch update (stock decrement)

mutation update_goods($where: goods_bool_exp!, $inc: goods_inc_input) { update_goods(where: $where, _inc: $inc) { returning { id stock } } }
{ "where": { "_and": [ { "id": { "_eq": 10001 } }, { "stock": { "_gte": 2 } } ] }, "inc": { "stock": -2 } }

By primary key

mutation UpdateGoodsByPk($pk_columns: goods_pk_columns_input!, $set: goods_set_input) { update_goods_by_pk(pk_columns: $pk_columns, _set: $set) { id name } }

Delete data

Field patternDescription
delete_{table_name}Batch delete
delete_{table_name}_by_pkDelete by primary key

Batch delete

mutation($where: order_bool_exp!) { delete_order(where: $where) { returning { id } } }

By primary key

mutation DeleteOrderByPk($id: bigint!) { delete_order_by_pk(id: $id) { id } }

Transactions

Multiple mutations in one request run in a database transaction (all succeed or all roll back). Example: create order and decrement stock:

mutation( $objects_order: [order_insert_input!]!, $on_conflict_order: order_on_conflict!, $where_product: product_bool_exp!, $inc_product: product_inc_input! ) { step1_insert: insert_order( objects: $objects_order, on_conflict: $on_conflict_order ) { returning { id } } step2_update: update_product( where: $where_product, _inc: $inc_product ) { returning { id } } }

Use aliases (step1_insert, step2_update) to distinguish results.

Actionflow invocation

Actionflows encapsulate multi-step backend logic. Sync and async patterns use mutation to start and query / subscription for async results.

FieldTypeDescription
fz_invoke_action_flowmutationSync invoke; returns output in same response
fz_invoke_action_flow_default_by_latest_versionmutationSync invoke default/latest version
fz_create_action_flow_taskmutationAsync task; returns taskId
fz_listen_action_flow_resultsubscriptionListen for task status/output
fz_action_flow_resultqueryPoll task result
ParameterDescription
actionFlowIdActionflow id
versionIdVersion (optional for latest)
argsInput JSON
taskIdAsync task id

Sync invoke

mutation InvokeActionFlow($actionFlowId: String!, $versionId: Int!, $args: Json!) { fz_invoke_action_flow(actionFlowId: $actionFlowId, versionId: $versionId, args: $args) }

Async: create task

mutation CreateActionFlowTask($actionFlowId: String!, $versionId: Int, $args: Json!) { fz_create_action_flow_task(actionFlowId: $actionFlowId, versionId: $versionId, args: $args) }

Listen (subscription)

subscription ListenActionFlowTask($taskId: Long!) { fz_listen_action_flow_result(taskId: $taskId) { status output } }
FieldTypeDescription
statusTaskStatusCREATED, PROCESSING, COMPLETED, FAILED, STREAMING, TIME_OUT
outputJsonActionflow output node data

AI Agent invocation

AI Agents use mutation to start and subscription for streaming results.

Media inputs use {name}_id or {name}_ids (e.g. video_id).

FieldTypeDescription
fz_zai_create_conversationmutationCreate conversation
fz_zai_listen_conversation_resultsubscriptionStream/final result
fz_zai_send_ai_messagemutationContinue conversation
fz_zai_stop_respondingmutationStop generation
fz_zai_delete_conversationmutationDelete conversation

Create and listen

mutation ZAICreateConversation($inputArgs: Map_String_ObjectScalar!, $zaiConfigId: String!) { fz_zai_create_conversation(inputArgs: $inputArgs, zaiConfigId: $zaiConfigId) }
subscription ListenZAIConversation($conversationId: Long!) { fz_zai_listen_conversation_result(conversationId: $conversationId) { conversationId status data reasoningContent images { id url } } }

Streaming: STREAMING pushes partial text; final COMPLETED includes full data. Structured output returns once on COMPLETED. Image models populate images.

Send message / stop / delete

mutation ZAISendAiMessage( $conversationId: Long!, $text: String, $imageIds: [Long], $fileId: Long, $videoId: Long ) { fz_zai_send_ai_message( conversationId: $conversationId, text: $text, imageIds: $imageIds, fileId: $fileId, videoId: $videoId ) }

External API invocation

Imported APIs are exposed as GraphQL fields (query or mutation per configuration).

Field patternDescription
operation_{thirdPartyApiId}Legacy OpenAPI import
fz_api_{apiId}API Workspace
ParameterDescription
fz_bodyLegacy request body
AuthorizationLegacy auth header
inputAPI Workspace input type

External APIs configured only inside Actionflows are not directly exposed to the client; the client calls the Actionflow instead. Non-2xx responses fail the Actionflow node.

Legacy third-party API

mutation CreateCalendarEvent( $summary: String, $location: String, $authorization: String ) { operation_create_calendar_event( fz_body: { summary: $summary, location: $location }, Authorization: $authorization ) { responseCode field_200_json { id status htmlLink } } }

Check responseCode; field_200_json may be empty on 4xx/5xx.

API Workspace

mutation CallApi($input: fz_api_create_order_input!) { fz_api_create_order(input: $input) { responseCode responseStatus responseContentType fz_api_create_order_response { order_id status } } }
Last updated on