GraphQL

FLXBL generates a GraphQL API from each tenant's active schema. Use it when clients need typed selections, nested relationship reads, cursor pagination, batch mutations, vector search, or GraphQL subscriptions.

Generated GraphQL API

The HTTP endpoint is tenant-scoped. Download the generated schema when you want GraphQL clients, codegen tools, or IDEs to discover the current fields. Send API keys or access tokens with the standard Authorization: Bearer header.

# HTTP GraphQL endpoint
POST https://api.flxbl.dev/api/v1/dynamic-gql/{tenantId}

# Download generated schema
GET https://api.flxbl.dev/api/v1/dynamic-gql/{tenantId}/schema.graphql

Query Fields

Root list fields accept GraphQL-style filter operators, full-text search, offset pagination, and target-field ordering.

query {
  users(
    where: {
      AND: [
        { status: { equals: "active" } }
        { posts_some: { title: { contains: "GraphQL" } } }
      ]
    }
    search: "platform"
    limit: 20
    offset: 0
    orderBy: [{ field: "createdAt", direction: DESC }]
  ) {
    id
    name
    email
  }
}
Syntax note: GraphQL filters use operators such as equals and contains. The REST Query DSL and TypeScript SDK use $eq, $contains, and related operators.

Relationship Filters

Relationship predicates can be used in root where inputs. For example, posts_some matches users with at least one related post matching the nested condition.

Nested Relationship Field Arguments

Simple relationship fields accept arguments on the field selection. The nested where filter is scoped to related target nodes for the current source record and tenant.

query {
  users(where: { status: { equals: "active" } }, limit: 20) {
    id
    name
    posts(
      where: { title: { contains: "GraphQL" } }
      limit: 5
      offset: 0
      orderBy: [{ field: "createdAt", direction: DESC }]
    ) {
      id
      title
      createdAt
    }
  }
}

Relationship Properties

Relationships with properties use connection fields. Use nodeWhere for related target-node fields and edgeWhere for relationship properties.

query {
  users {
    groupsConnection(
      nodeWhere: { status: { equals: "active" } }
      edgeWhere: { role: { equals: "admin" } }
      limit: 10
      offset: 0
      orderBy: [{ field: "name", direction: ASC }]
    ) {
      edges {
        role
        node {
          id
          name
        }
      }
    }
  }
}

Relationship Mutations By ID

For relationships with properties, FLXBL generates by-id update mutations such as updateUserGroupsMemberOfRelationshipById. By-id delete mutations such as deleteUserGroupsMemberOfRelationshipById are generated so clients can remove the exact edge returned by relationship list and connection queries.

mutation {
  updateUserGroupsMemberOfRelationshipById(
    id: "rel_789"
    properties: { role: "owner" }
  ) {
    id
    role
    node {
      id
      name
    }
  }

  deleteUserGroupsMemberOfRelationshipById(id: "rel_789") {
    id
    from
    to
  }
}
Pagination note: Relationship-property connection fields currently use limit and offset. Root connection fields use Relay-style cursor arguments.

Cursor Pagination

Root *Connection fields support cursor pagination with first, after, last, and before.

query($after: String) {
  usersConnection(
    first: 20
    after: $after
    orderBy: [{ field: "createdAt", direction: DESC }]
  ) {
    edges {
      cursor
      node {
        id
        name
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

Vector Search

VECTOR-enabled entities can expose generated vector search fields. FLXBL accepts query vectors; your application is responsible for generating embeddings with the same dimensions as the schema field.

query {
  documentVectorSearch(input: {
    field: "embedding"
    vector: [1, 0, 0, 0]
    topK: 5
    where: { category: { equals: "tutorial" } }
  }) {
    score
    data {
      id
      title
      category
    }
  }
}

Batch Mutations

GraphQL batch mutations mirror REST batch behavior and return successful rows, failed rows, and counts.

mutation {
  batchCreateProduct(input: [
    { name: "Widget A", price: 29.99 },
    { name: "Widget B", price: 39.99 }
  ]) {
    successful { id name price }
    failed { index error { code message field } }
    successCount
    failureCount
  }
}

Realtime

Entity lifecycle events are available over GraphQL subscriptions using the graphql-transport-ws subprotocol. See GraphQL Subscriptions for WebSocket connection and JWT authentication examples.

Next Steps