API Reference
FLXBL automatically generates REST and GraphQL APIs from your schema. This reference covers all available endpoints and operations.
Base URL
All API requests use this base URL:
https://api.flxbl.dev/api/v1 For self-hosted instances, use your configured URL.
Authentication
Use API keys for programmatic access to the FLXBL Dynamic API.
Include your API key in the Authorization header:
# API Key Authentication
curl -X GET https://api.flxbl.dev/api/v1/dynamic/Product \
-H "Authorization: Bearer flxbl_ab12cd34_..."
# Get your API key from your FLXBL dashboard at platform.flxbl.devGenerate API keys from your FLXBL dashboard at platform.flxbl.dev. API keys are scoped to your tenant and provide access to the Dynamic API endpoints.
REST API Endpoints
For each entity in your schema, these endpoints are generated:
# Entity CRUD Operations
GET /api/v1/dynamic/{Entity} # List all
POST /api/v1/dynamic/{Entity} # Create
GET /api/v1/dynamic/{Entity}/:id # Read
PUT /api/v1/dynamic/{Entity}/:id # Full update
PATCH /api/v1/dynamic/{Entity}/:id # Partial update
DELETE /api/v1/dynamic/{Entity}/:id # Delete
POST /api/v1/dynamic/{Entity}/query # Query with DSL
# Vector Search
POST /api/v1/dynamic/{Entity}/vector-search # Similarity search
# Relationship Operations
POST /api/v1/dynamic/{Entity}/:id/relationships/{rel}
GET /api/v1/dynamic/{Entity}/:id/relationships/{rel}?direction=out
PATCH /api/v1/dynamic/{Entity}/:id/relationships/{rel}/:targetId
DELETE /api/v1/dynamic/{Entity}/:id/relationships/{rel}/:targetId
# File Storage
POST /api/v1/files/upload-url # Get presigned upload URL
POST /api/v1/files/:id/confirm # Confirm upload
GET /api/v1/files/:id/download-url # Get presigned download URL
GET /api/v1/files/:id # Get file metadata
GET /api/v1/files # List files
DELETE /api/v1/files/:id # Delete file
# GraphQL Endpoint
POST /api/v1/dynamic-gql/:tenantId
GET /api/v1/dynamic-gql/:tenantId/schema.graphqlImportant: Entity names in URLs are case-sensitive. Use the exact name from your schema (e.g.,Productnotproducts).
Create (POST)
# Create a product
curl -X POST https://api.flxbl.dev/api/v1/dynamic/Product \
-H "Authorization: Bearer flxbl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Wireless Headphones",
"price": 299.99,
"inStock": true,
"tags": ["electronics", "audio"]
}'
# Response
{
"id": "node_abc123",
"name": "Wireless Headphones",
"price": 299.99,
"inStock": true,
"tags": ["electronics", "audio"],
"createdAt": "2025-01-15T10:30:00Z",
"updatedAt": "2025-01-15T10:30:00Z"
}Read (GET)
# Get a product by ID
curl -X GET https://api.flxbl.dev/api/v1/dynamic/Product/node_abc123 \
-H "Authorization: Bearer flxbl_your_api_key"
# List all products
curl -X GET https://api.flxbl.dev/api/v1/dynamic/Product \
-H "Authorization: Bearer flxbl_your_api_key"Update (PUT/PATCH)
# Full update (PUT) - replaces all fields
curl -X PUT https://api.flxbl.dev/api/v1/dynamic/Product/node_abc123 \
-H "Authorization: Bearer flxbl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Premium Wireless Headphones",
"price": 349.99,
"inStock": true,
"tags": ["electronics", "audio", "premium"]
}'
# Partial update (PATCH) - only updates specified fields
curl -X PATCH https://api.flxbl.dev/api/v1/dynamic/Product/node_abc123 \
-H "Authorization: Bearer flxbl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"price": 279.99
}'Delete (DELETE)
# Delete a product
# IMPORTANT: Do NOT include Content-Type header for DELETE without body
curl -X DELETE https://api.flxbl.dev/api/v1/dynamic/Product/node_abc123 \
-H "Authorization: Bearer flxbl_your_api_key" Important: Do NOT include Content-Type: application/json
header for DELETE requests without a body. This will cause a 400 error.
Relationship Operations
Manage relationships between entities:
# Create a relationship
curl -X POST https://api.flxbl.dev/api/v1/dynamic/Product/node_abc/relationships/BELONGS_TO \
-H "Authorization: Bearer flxbl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"targetId": "node_category_xyz",
"properties": {
"addedAt": "2025-01-15T10:30:00Z"
}
}'
# Get relationships
curl -X GET "https://api.flxbl.dev/api/v1/dynamic/Product/node_abc/relationships/BELONGS_TO?direction=out" \
-H "Authorization: Bearer flxbl_your_api_key"
# Delete a relationship
curl -X DELETE https://api.flxbl.dev/api/v1/dynamic/Product/node_abc/relationships/BELONGS_TO/node_category_xyz \
-H "Authorization: Bearer flxbl_your_api_key"Batch Operations
FLXBL supports batch operations for high-performance bulk data processing. All batch operations are atomic (all-or-nothing) and support up to 1,000 items per request.
Batch Create (POST)
Create multiple entities in a single request:
# Batch create multiple products
curl -X POST https://api.flxbl.dev/api/v1/dynamic/Product/batch \
-H "Authorization: Bearer flxbl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "name": "Widget A", "price": 29.99 },
{ "name": "Widget B", "price": 39.99 }
]
}'
# Response
{
"successful": [
{ "id": "node_abc", "name": "Widget A", "price": 29.99, ... },
{ "id": "node_def", "name": "Widget B", "price": 39.99, ... }
],
"failed": [],
"totalCount": 2,
"successCount": 2,
"failureCount": 0,
"stats": {
"processingTimeMs": 150,
"validationTimeMs": 20,
"databaseTimeMs": 130
}
}Batch Update (PATCH)
Update multiple entities at once. Each item requires an id and a data object:
# Batch update multiple products
curl -X PATCH https://api.flxbl.dev/api/v1/dynamic/Product/batch \
-H "Authorization: Bearer flxbl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "id": "node_abc", "data": { "price": 24.99 } },
{ "id": "node_def", "data": { "price": 34.99 } }
]
}'Batch Delete (DELETE)
Delete multiple entities by their IDs:
# Batch delete multiple products
curl -X DELETE https://api.flxbl.dev/api/v1/dynamic/Product/batch \
-H "Authorization: Bearer flxbl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"ids": ["node_abc", "node_def", "node_ghi"]
}'Response Format
All batch operations return a consistent response format with success/failure details and performance metrics:
# Response format (all batch operations)
{
"successful": [ ... ], # Successfully processed entities
"failed": [ # Failed items with error details
{
"index": 1,
"item": { "name": "Invalid" },
"error": {
"code": "VALIDATION_ERROR",
"message": "Field 'price' is required",
"field": "price"
}
}
],
"totalCount": 10, # Total items in request
"successCount": 9, # Successfully processed
"failureCount": 1, # Failed items
"stats": { # Performance metrics
"processingTimeMs": 150,
"validationTimeMs": 20,
"databaseTimeMs": 130
}
}| Field | Description |
|---|---|
successful | Array of successfully processed entities |
failed | Array of failed items with index and error details |
successCount | Number of successfully processed items |
failureCount | Number of failed items |
stats | Performance metrics (processing, validation, database time) |
Note: Batch operations are pre-validated before any database writes. If validation fails for any item, the entire batch is rejected.
Vector Search
Perform cosine similarity search on entities with VECTOR fields.
This is useful for semantic search, recommendations, and RAG applications.
Endpoint
POST /api/v1/dynamic/{Entity}/vector-search Request Body
| Field | Type | Description |
|---|---|---|
field | string | Name of the VECTOR field to search against (required) |
vector | number[] | Query vector — dimensions must match the field's vectorDimensions (required) |
topK | number | Maximum results to return, 1–100 (default: 10) |
where | object | Optional filter conditions applied after similarity ranking |
select | string[] | Optional fields to include in response (default: all) |
Example
# Vector similarity search on a Product's embedding field
curl -X POST https://api.flxbl.dev/api/v1/dynamic/Product/vector-search \
-H "Authorization: Bearer flxbl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"field": "embedding",
"vector": [0.1, 0.2, 0.3, "...1536 dimensions..."],
"topK": 5,
"where": {
"isActive": { "$eq": true }
},
"select": ["name", "price", "description"]
}'
# Response
[
{
"data": {
"id": "node_abc123",
"name": "Wireless Headphones",
"price": 299.99,
"description": "Premium noise-canceling headphones"
},
"score": 0.95
},
{
"data": {
"id": "node_def456",
"name": "Bluetooth Speaker",
"price": 149.99,
"description": "Portable wireless speaker"
},
"score": 0.87
}
]
Each result includes a score (0–1) representing cosine similarity,
where 1 is an exact match. Use the where parameter to filter results
by any field, and select to control which fields are returned.
Note: The query vector's dimensions must exactly match the field'svectorDimensionsconfiguration. For programmatic usage, seeclient.vectorSearch()in the SDK.
File Storage
FLXBL provides S3-compatible file storage with presigned URLs for secure,
direct-to-storage uploads and downloads. Files can be associated with entities
via FILE fields.
Upload Workflow
File uploads use a three-step presigned URL workflow:
- Request upload URL —
POST /api/v1/files/upload-urlwith file metadata - Upload to S3 —
PUTthe file directly to the presigned URL - Confirm upload —
POST /api/v1/files/:id/confirmto finalize
# Step 1: Get a presigned upload URL
curl -X POST https://api.flxbl.dev/api/v1/files/upload-url \
-H "Authorization: Bearer flxbl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"fileName": "product-hero.jpg",
"mimeType": "image/jpeg",
"sizeBytes": 2048576
}'
# Response
{
"fileId": "file_abc123",
"uploadUrl": "https://s3.amazonaws.com/bucket/...",
"expiresAt": "2026-01-15T11:30:00Z"
}
# Step 2: Upload the file directly to S3
curl -X PUT "https://s3.amazonaws.com/bucket/..." \
-H "Content-Type: image/jpeg" \
--data-binary @product-hero.jpg
# Step 3: Confirm the upload
curl -X POST https://api.flxbl.dev/api/v1/files/file_abc123/confirm \
-H "Authorization: Bearer flxbl_your_api_key"
# Response
{
"id": "file_abc123",
"tenantId": "tenant_xyz",
"fileName": "product-hero.jpg",
"mimeType": "image/jpeg",
"sizeBytes": 2048576,
"createdAt": "2026-01-15T10:30:00Z"
}Download
Request a presigned download URL and fetch the file directly from S3:
# Get a presigned download URL
curl -X GET https://api.flxbl.dev/api/v1/files/file_abc123/download-url \
-H "Authorization: Bearer flxbl_your_api_key"
# Response
{
"url": "https://s3.amazonaws.com/bucket/...",
"fileName": "product-hero.jpg",
"mimeType": "image/jpeg",
"expiresAt": "2026-01-15T11:30:00Z"
}
# Download the file
curl -O "https://s3.amazonaws.com/bucket/..."File Metadata
| Field | Description |
|---|---|
id | Unique file identifier |
fileName | Original file name |
mimeType | MIME type (e.g., image/jpeg) |
sizeBytes | File size in bytes (max 100 MB) |
entityName | Optional associated entity name |
entityId | Optional associated entity ID |
fieldName | Optional associated field name |
createdAt | Upload confirmation timestamp |
Other File Endpoints
GET /api/v1/files/:id— Get file metadataGET /api/v1/files?entityName=Product&limit=50— List files with optional filtersDELETE /api/v1/files/:id— Delete a file (returns 204)
Tip: FLXBL supports any S3-compatible storage (AWS S3, MinIO, DigitalOcean Spaces, etc.).
Configure your storage backend via the FILE_STORAGE_* environment variables.
GraphQL API
FLXBL also generates a complete GraphQL API. The endpoint requires your tenant ID:
# GraphQL endpoint
POST /api/v1/dynamic-gql/:tenantId
# Query example
query {
products(where: { inStock: { equals: true } }, limit: 10) {
id
name
price
belongsTo {
id
name
}
}
}
# Count query - get total count for pagination
query {
productsCount(where: { inStock: { equals: true } })
}
# Returns: { "data": { "productsCount": 157 } }
# Query with sorting
query {
products(
where: { inStock: { equals: true } }
orderBy: "price"
orderDirection: ASC
limit: 20
offset: 0
) {
id
name
price
}
}
# Mutation example
mutation {
createProduct(input: {
name: "New Product"
price: 99.99
}) {
id
name
createdAt
}
}Download the GraphQL schema:
GET /api/v1/dynamic-gql/{tenantId}/schema.graphql Cursor-Based Pagination
FLXBL implements the Relay Connection specification for cursor-based pagination, providing stable, efficient pagination even when data changes.
# GraphQL cursor pagination (Relay spec)
query {
productsConnection(first: 10) {
edges {
cursor
node {
id
name
price
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
}
totalCount
}
}
# Next page using cursor
query {
productsConnection(first: 10, after: "eyJpZCI6Im5vZGVfMTAifQ==") {
edges {
cursor
node { id name }
}
pageInfo { hasNextPage endCursor }
}
}
# Backward pagination
query {
productsConnection(last: 10, before: "eyJpZCI6Im5vZGVfMjAifQ==") {
edges { cursor node { id name } }
pageInfo { hasPreviousPage startCursor }
}
}Pagination arguments:
| Argument | Description |
|---|---|
first | Number of items to fetch (forward pagination, max 100) |
after | Cursor to start after (use endCursor from previous page) |
last | Number of items to fetch (backward pagination, max 100) |
before | Cursor to start before (use startCursor from previous page) |
Important: You cannot usefirstandlasttogether. Usefirst/afterfor forward pagination orlast/beforefor backward pagination.
GraphQL Batch Mutations
GraphQL also supports batch mutations for bulk operations with the same semantics as REST batch endpoints:
# Batch create mutation
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
}
}
# Batch update mutation
mutation {
batchUpdateProduct(input: [
{ id: "node_abc", data: { price: 24.99 } },
{ id: "node_def", data: { price: 34.99 } }
]) {
successful { id name price }
successCount
}
}
# Batch delete mutation
mutation {
batchDeleteProduct(ids: ["node_abc", "node_def"]) {
successful { id }
successCount
failureCount
}
}Available batch mutations for each entity:
batchCreate{Entity}- Create multiple entitiesbatchUpdate{Entity}- Update multiple entities by IDbatchDelete{Entity}- Delete multiple entities by ID
Integrate with External Tools
FLXBL generates standard OpenAPI and GraphQL specifications that work with your favorite API tools.
Postman / Insomnia
Import your schema's OpenAPI spec directly into Postman or Insomnia for interactive API testing:
- Download your OpenAPI spec:
GET /api/v1/schemas/:schemaId/openapi.json - In Postman: Import → File → Select openapi.json
- All your entity endpoints, authentication, and request bodies are ready to use
Apollo Sandbox / GraphiQL
Connect Apollo Sandbox or GraphiQL to your GraphQL endpoint for schema exploration and query building:
- Point your GraphQL client to
POST /api/v1/dynamic-gql/:tenantId - Include your API key in the
Authorization: Bearer flxbl_xxxheader - Download the schema:
GET /api/v1/dynamic-gql/:tenantId/schema.graphql
Tip: The GraphQL endpoint supports introspection, so tools like Apollo Sandbox will automatically discover your schema's types and operations.
Rate Limiting
FLXBL implements multi-layer rate limiting:
| Layer | Default Limit | Scope |
|---|---|---|
| Global | 500 req/min | Per IP address |
| Auth endpoints | 20 req/min | Per IP address |
| Tenant | 300 req/min | Per tenant |
Rate limit information is included in response headers:
# Rate limit headers in response
X-RateLimit-Limit: 100 # Max requests per window
X-RateLimit-Remaining: 95 # Requests remaining
X-RateLimit-Reset: 60 # Seconds until reset
When rate limited, the API returns 429 Too Many Requests.
Use the X-RateLimit-Reset header to know when to retry.
Error Responses
Errors follow a consistent format:
| Status | Meaning |
|---|---|
| 400 | Bad request - Invalid input or missing required fields |
| 401 | Unauthorized - Missing or invalid authentication |
| 403 | Forbidden - Insufficient permissions |
| 404 | Not found - Entity or resource doesn't exist |
| 429 | Too many requests - Rate limit exceeded |
| 500 | Internal error - Server-side issue |
Next Steps
- SDK - Type-safe client for programmatic API access
- CLI - Generate typed SDKs and manage schemas from your terminal
- Query DSL - Learn the powerful query language
- Schema Design - Design better schemas
- MCP Integration - AI-assisted development