Skip to Content
DocumentationDevelopersRuntime API Reference

Runtime API Reference

Momen generates a Runtime GraphQL API for every project. Use it to access your project database and invoke Actionflows, AI Agents, and third-party APIs from a custom frontend, server application, or external system.

Your data model and feature configuration determine the generated GraphQL schema. This reference covers stable calling conventions and naming patterns. For the exact fields, arguments, and return types in your project, use GraphiQL in Developer access.

Get started

Open Developer access in the editor to access the following project-specific values:

  • GraphQL API URL for queries and mutations.
  • GraphQL subscription URL for subscriptions.
  • Admin Bearer Token for project-level backend access.
  • GraphiQL for browsing the current schema and testing operations.

Endpoint URLs follow these patterns:

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

After changing the data model, Actionflow inputs or outputs, AI Agents, or third-party APIs, sync or publish the backend changes and then refresh the schema in GraphiQL.

HTTP requests

Queries and mutations use a standard GraphQL JSON body:

{ "query": "query GetPosts($limit: Int!) { post(limit: $limit) { id title } }", "operationName": "GetPosts", "variables": { "limit": 10 } }

Authentication

The Runtime API evaluates permissions using the identity attached to each request.

IdentityAuthenticationUse case
GuestNo Authorization headerAccess data and features available to guests.
Current userAuthorization: Bearer <jwt>Run requests with the signed-in user’s roles and permissions.
Project administratorAuthorization: Bearer <admin_token>Trusted servers, scripts, and local development tools that require project-level access.
⚠️

The Admin Bearer Token grants elevated project access. Never include it in a website, client application, public repository, or any code delivered to end users.

Get a user JWT

Each sign-in method has its own authentication field. This example obtains a JWT with a username and password:

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

Set register to true to register and sign in, or false to sign in to an existing account. Send the returned jwt.token in subsequent HTTP requests:

Authorization: Bearer <jwt>

Authenticate subscriptions

Subscriptions use the graphql-ws protocol. Pass the token in the payload of the connection_init message:

{ "type": "connection_init", "payload": { "authToken": "<jwt_or_admin_token>" } }

Requests, responses, and errors

The Runtime API supports three GraphQL operation types:

TypePurposeCommon use
queryRead dataQuery tables, check async tasks, or request an upload URL.
mutationChange data or start executionCreate, update, or delete data; invoke an Actionflow or AI Agent.
subscriptionListen for ongoing resultsReceive Actionflow, AI Agent, or data updates.

GraphQL returns only the fields selected by the operation. A successful response normally contains data:

{ "data": { "post": [{ "id": 1, "title": "Hello" }] } }

Failed fields appear in errors. A GraphQL response can contain partial data and errors at the same time, so clients should handle them separately:

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

When troubleshooting, check message, path, and the request identifier in the response, then locate the corresponding request in runtime logs.

API reference

Database

Momen generates table queries, relation fields, aggregates, and mutations from your data model. The examples below use a post table. Replace the names and types with those shown in your project’s GraphiQL schema.

Data types

Momen typeGraphQL typeDescription
TextStringText value.
Big integerbigint or a generated long typeCommonly used for record IDs; use the type shown in the schema.
DecimalDecimalHigh-precision decimal.
BooleanBooleantrue or false.
JSONBjsonbJSON data.
Date and time with time zonetimestamptzA date and time with time-zone information.
Time with time zonetimetzA time of day with time-zone information.
DatedateA calendar date without a time.
LocationgeographyGeographic coordinates.
ImageFZ_ImageImage asset.
VideoFZ_VideoVideo asset.
FileFZ_FileFile asset.

When writing media fields, use {field_name}_id for a single asset and {field_name}_ids for an asset list. For example, an image field named cover uses the input field cover_id.

Query data

Common generated query fields include the following. Some fields are generated only when the corresponding feature or data type is present.

Field patternDescription
{table_name}Query a list with filtering, sorting, and pagination.
{table_name}_by_pkQuery one record by primary key.
{table_name}_aggregateReturn counts, sums, and other aggregates.
{table_name}_group_byGroup query results.
fz_{table_name}_by_{column_name}Run a distance query against a location field.

List fields commonly accept these arguments:

ArgumentDescription
whereFilter expression, usually {table_name}_bool_exp.
order_bySort expression.
distinct_onReturn distinct values for selected fields.
limitMaximum number of records.
offsetNumber of records to skip.

Common comparison operators include _eq, _neq, _gt, _gte, _lt, _lte, _in, _nin, _like, _ilike, and _is_null. Combine conditions with _and, _or, and _not.

query GetPublishedPosts($where: post_bool_exp!, $limit: Int!) { post( where: $where order_by: { created_at: desc } limit: $limit ) { id title author { id name } } }
{ "where": { "status": { "_eq": "published" }, "author": { "name": { "_ilike": "%lee%" } } }, "limit": 20 }

Operator-first filters

Use an operator-first filter when a database function must transform a field before comparison. This example checks whether the month in created_at is December:

{ "where": { "_eq": { "left_operand": { "extract": { "field": "created_at", "part": "MONTH" } }, "right_operand": 12 } } }

Available functions and arguments depend on the field type and current schema. Inspect the generated input type in GraphiQL.

Insert data

mutation CreatePost($object: post_insert_input!) { insert_post_one(object: $object) { id title created_at } }
{ "object": { "title": "My first post", "status": "draft", "cover_id": 1020000000000097 } }

Use insert_{table_name} for a batch insert. Its objects argument accepts a list and the response can include affected_rows and selected returning fields.

Update data

mutation PublishPost($id: bigint!, $set: post_set_input!) { update_post_by_pk(pk_columns: { id: $id }, _set: $set) { id status } }
{ "id": 100000000000001, "set": { "status": "published" } }

Use update_{table_name} for a batch update. Select records with where and apply changes with arguments such as _set and _inc.

Delete data

mutation DeletePost($id: bigint!) { delete_post_by_pk(id: $id) { id } }

Use delete_{table_name}(where: ...) to delete multiple records. Check relation and deletion rules before running a batch delete.

Transactions

Place multiple database write fields in one mutation to run them as one atomic batch. Momen commits all database operations if they succeed and rolls back the entire batch if any of them fails.

mutation CreateOrder($order: order_insert_input!, $items: [order_item_insert_input!]!) { insert_order_one(object: $order) { id } insert_order_item(objects: $items) { affected_rows } }

This guarantee covers database writes in the mutation. Side effects from external HTTP requests, AI Agents, or Actionflows do not participate in the database transaction.

Actionflows

Actionflow inputs and outputs come from the project configuration. After syncing or publishing changes, inspect the current fields and types in GraphiQL. Current integrations invoke the deployed Actionflow without selecting a version.

FieldTypeDescription
fz_invoke_action_flow_default_by_latest_versionmutationInvoke an Actionflow synchronously and return its outputs.
fz_create_action_flow_taskmutationCreate an async task and return its task ID.
fz_listen_action_flow_resultsubscriptionListen for an async task result.
fz_action_flow_resultqueryPoll an async task result.

The versionId argument and fz_invoke_action_flow field remain in the schema only for backward compatibility with existing integrations. Do not pass an Actionflow version in new integrations.

Synchronous invocation

mutation InvokeActionFlow($actionFlowId: String!, $args: Json!) { fz_invoke_action_flow_default_by_latest_version( actionFlowId: $actionFlowId args: $args ) }
{ "actionFlowId": "d3ea4f95-5d34-46e1-b940-91c4028caff5", "args": { "order_id": 10001 } }

The response is the set of outputs declared by the Actionflow.

Asynchronous invocation

Create a task first:

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

The returned long integer is the taskId. Listen for its result with a subscription:

subscription ListenActionFlowResult($taskId: Long!) { fz_listen_action_flow_result(taskId: $taskId) { status output } }

If subscriptions are not suitable for your client, poll the result instead:

query GetActionFlowResult($taskId: Long!) { fz_action_flow_result(taskId: $taskId) { status output } }

output contains the outputs declared by the Actionflow. Inspect the TaskStatus enum in GraphiQL for the available status values.

AI Agents

The Runtime Schema retains the fz_zai_* prefix for compatibility. These fields invoke the product feature named AI Agent.

FieldTypeDescription
fz_zai_create_conversationmutationCreate a conversation.
fz_zai_listen_conversation_resultsubscriptionListen for streaming and final results.
fz_zai_send_ai_messagemutationSend a message to an existing conversation.
fz_zai_provide_more_informationmutationProvide information requested by a tool call.
fz_zai_stop_respondingmutationStop the current response.
fz_zai_delete_conversationmutationDelete a conversation.

The fields in inputArgs come from the AI Agent configuration. Use the configured name for ordinary inputs, {name}_id for a single media input, and {name}_ids for a media list.

mutation CreateAgentConversation( $inputArgs: Map_String_ObjectScalar! $agentId: String! ) { fz_zai_create_conversation( inputArgs: $inputArgs zaiConfigId: $agentId ) }
{ "agentId": "zai_01HZXEXAMPLE", "inputArgs": { "question": "Summarize this article", "cover_id": 1020000000000097 } }

Listen with the returned conversationId:

subscription ListenAgentResult($conversationId: Long!) { fz_zai_listen_conversation_result(conversationId: $conversationId) { conversationId status data reasoningContent images { id url } } }

Conversation status values include CREATED, IN_PROGRESS, THINKING_CHAIN_STREAMING, STREAMING, COMPLETED, FAILED, and CANCELED. Streaming text may arrive in multiple messages; use a final status to determine when the response has ended.

For later turns in a conversation, use the fixed message arguments rather than the custom input names used at creation:

mutation SendAgentMessage( $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 ) }

Sending a message, stopping a response, and deleting a conversation require access to that conversation. Continue listening with the same conversationId after sending a message.

Third-party APIs

An API configured and published under API generates a field named fz_api_{api_unique_id}. The operation type, input type, and response fields depend on the API configuration. Copy the actual operation from GraphiQL.

mutation CallCreateOrderApi($input: fz_api_create_order_input!) { fz_api_create_order(input: $input) { responseCode responseStatus responseContentType fz_api_create_order_response { order_id status } } }
{ "input": { "order_id": 10001, "amount": 99 } }

Check responseCode and responseStatus before reading the generated structured response field.

Legacy third-party APIs may still expose an operation_{operationId} field and generate an fz_body argument. Existing projects should follow the fields that remain in GraphiQL. Use the current API feature for new integrations.

Media

Uploading an image, video, or file through the Runtime API has three steps:

  1. Calculate the MD5 digest of the file contents and encode it as Base64.
  2. Call a V2 presigned field to receive uploadUrl, uploadHeaders, contentType, and the asset ID.
  3. Upload the original file with the returned URL and headers, then use the asset ID in a data mutation, Actionflow, or AI Agent call.
AssetSingle-asset fieldBatch fieldAsset ID
ImagegetImagePresignedUrlV2presignedImageListV2imageId
VideogetVideoPresignedUrlV2presignedVideoListV2videoId
FilegetFilePresignedUrlV2fileId

The following example prepares an image upload. Inspect GraphiQL for valid imageSuffix and acl enum values:

query PrepareImageUpload($md5: String!, $format: MediaFormat!) { getImagePresignedUrlV2(imgMd5Base64: $md5, imageSuffix: $format) { imageId uploadUrl uploadHeaders downloadUrl contentType } }

Upload the raw file to uploadUrl with every header returned in uploadHeaders. Do not omit or rewrite signed headers.

Troubleshooting

ProblemWhat to check
permission deniedConfirm the request identity and its permissions for the data, Actionflow, AI Agent, or API.
Cannot query fieldRefresh the GraphiQL schema, confirm the change has been synced or published, and use the generated field name.
Variable type mismatchCheck nullability, list structure, and scalar types in GraphiQL instead of copying types from another project.
HTTP request succeeds but data is emptyInspect errors in the same response. For a third-party API, also inspect responseCode.
Subscription returns no resultUse the subscription URL, the graphql-ws protocol, and connection_init.payload.authToken.
Async Actionflow does not completePoll with fz_action_flow_result, then inspect Actionflow runtime logs for node errors or timeouts.
AI Agent conversation cannot continueCheck the conversation status, ownership, and whether a previous response is still running.
Uploaded asset cannot be usedInclude every returned uploadHeaders entry and use the asset ID from the presigned response.
Third-party API field is missingConfirm the API has been published, then search GraphiQL for its unique API identifier.

For general GraphQL syntax, see the GraphQL documentation.

Last updated on