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-subscriptionAfter 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.
| Identity | Authentication | Use case |
|---|---|---|
| Guest | No Authorization header | Access data and features available to guests. |
| Current user | Authorization: Bearer <jwt> | Run requests with the signed-in user’s roles and permissions. |
| Project administrator | Authorization: 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:
| Type | Purpose | Common use |
|---|---|---|
query | Read data | Query tables, check async tasks, or request an upload URL. |
mutation | Change data or start execution | Create, update, or delete data; invoke an Actionflow or AI Agent. |
subscription | Listen for ongoing results | Receive 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 type | GraphQL type | Description |
|---|---|---|
| Text | String | Text value. |
| Big integer | bigint or a generated long type | Commonly used for record IDs; use the type shown in the schema. |
| Decimal | Decimal | High-precision decimal. |
| Boolean | Boolean | true or false. |
| JSONB | jsonb | JSON data. |
| Date and time with time zone | timestamptz | A date and time with time-zone information. |
| Time with time zone | timetz | A time of day with time-zone information. |
| Date | date | A calendar date without a time. |
| Location | geography | Geographic coordinates. |
| Image | FZ_Image | Image asset. |
| Video | FZ_Video | Video asset. |
| File | FZ_File | File 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 pattern | Description |
|---|---|
{table_name} | Query a list with filtering, sorting, and pagination. |
{table_name}_by_pk | Query one record by primary key. |
{table_name}_aggregate | Return counts, sums, and other aggregates. |
{table_name}_group_by | Group query results. |
fz_{table_name}_by_{column_name} | Run a distance query against a location field. |
List fields commonly accept these arguments:
| Argument | Description |
|---|---|
where | Filter expression, usually {table_name}_bool_exp. |
order_by | Sort expression. |
distinct_on | Return distinct values for selected fields. |
limit | Maximum number of records. |
offset | Number 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.
| Field | Type | Description |
|---|---|---|
fz_invoke_action_flow_default_by_latest_version | mutation | Invoke an Actionflow synchronously and return its outputs. |
fz_create_action_flow_task | mutation | Create an async task and return its task ID. |
fz_listen_action_flow_result | subscription | Listen for an async task result. |
fz_action_flow_result | query | Poll 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.
| Field | Type | Description |
|---|---|---|
fz_zai_create_conversation | mutation | Create a conversation. |
fz_zai_listen_conversation_result | subscription | Listen for streaming and final results. |
fz_zai_send_ai_message | mutation | Send a message to an existing conversation. |
fz_zai_provide_more_information | mutation | Provide information requested by a tool call. |
fz_zai_stop_responding | mutation | Stop the current response. |
fz_zai_delete_conversation | mutation | Delete 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:
- Calculate the MD5 digest of the file contents and encode it as Base64.
- Call a V2 presigned field to receive
uploadUrl,uploadHeaders,contentType, and the asset ID. - Upload the original file with the returned URL and headers, then use the asset ID in a data mutation, Actionflow, or AI Agent call.
| Asset | Single-asset field | Batch field | Asset ID |
|---|---|---|---|
| Image | getImagePresignedUrlV2 | presignedImageListV2 | imageId |
| Video | getVideoPresignedUrlV2 | presignedVideoListV2 | videoId |
| File | getFilePresignedUrlV2 | — | fileId |
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
| Problem | What to check |
|---|---|
permission denied | Confirm the request identity and its permissions for the data, Actionflow, AI Agent, or API. |
Cannot query field | Refresh the GraphiQL schema, confirm the change has been synced or published, and use the generated field name. |
| Variable type mismatch | Check nullability, list structure, and scalar types in GraphiQL instead of copying types from another project. |
HTTP request succeeds but data is empty | Inspect errors in the same response. For a third-party API, also inspect responseCode. |
| Subscription returns no result | Use the subscription URL, the graphql-ws protocol, and connection_init.payload.authToken. |
| Async Actionflow does not complete | Poll with fz_action_flow_result, then inspect Actionflow runtime logs for node errors or timeouts. |
| AI Agent conversation cannot continue | Check the conversation status, ownership, and whether a previous response is still running. |
| Uploaded asset cannot be used | Include every returned uploadHeaders entry and use the asset ID from the presigned response. |
| Third-party API field is missing | Confirm the API has been published, then search GraphiQL for its unique API identifier. |
For general GraphQL syntax, see the GraphQL documentation .