Skip to main content
Quick Start Tutorial: Migrate your MongoDB Data API in 30 minutes - A step-by-step guide to get started with Modelence Data API.

What is MongoDB Data API

An open-source API to read, write, and aggregate data in MongoDB. The application can be deployed to Modelence Cloud or to any other cloud provider.
  • CRUD Operations: Insert, find, update, and delete documents
  • Advanced Querying: Aggregation pipelines and complex queries
  • Database Management: Collection and index management
  • Authentication: API key-based security
  • MongoDB Operations: Direct access to MongoDB features

Sandbox

Try the Data API live at data-api-demo.modelence.app to explore all endpoints and test operations without setup.

Project Setup

1. Create a new application

npx create-modelence-app@latest data-api --template data-api

2. Connect to Modelenece Cloud

  1. Open cloud.modelence.com create
  2. Create a new application and a local environment
  3. Click on Setting → Set up
  4. Follow the steps described in the modal

3. Start the Development Server

npm run dev
Your Data API will be available at http://localhost:3000

Core Components

DB Access

The MongoDB URL for Data API can be configured via the dataApi.mongodbUri setting in Application → Configuration at https://cloud.modelence.com/.
The Modelence framework uses the _system.mongodbUri configuration to connect to MongoDB. You can configure two different MongoDB instances to separate Modelence-specific collections from those accessible via Data API.

Authentication

The Data API supports two authentication methods:

1. Direct API Key Authentication

Set the api key as the value of ‘dataApi.apiKey’ in Modelence Cloud from the Application page. (Alternatively you can use DATA_API_KEY environment variable). Use the apiKey header in your requests:
apiKey: your-secure-api-key-here

2. Bearer Token Authentication

Alternatively, you can use Bearer token authentication by first obtaining an access token from the login endpoint: Login Endpoint: POST /auth/providers/api-key/login Request:
{
  "key": "your-api-key"
}
Response:
{
  "access_token": "eyJhbGc...",
  "refresh_token": "eyJhbGc...",
  "token_type": "Bearer",
  "expires_in": 1800
}
Then use the access token in the Authorization header:
Authorization: Bearer eyJhbGc...
Access tokens expire after 30 minutes. Use the refresh token to obtain a new access token without re-authenticating.

Available Endpoints

The API provides comprehensive MongoDB operations with full request/response specifications:

API Operations Reference

1. Find One Document (POST /data/v1/action/findOne)

Purpose: Retrieve a single document from a collection Request Fields:
{
  "collection": "string",          // Required: Collection name
  "database": "string",            // Optional: Database name (uses default if not specified)
  "filter": {},                    // Optional: Query filter object
  "projection": {}                 // Optional: Fields to include/exclude
}
Example Request:
{
  "collection": "users",
  "filter": { "email": "user@example.com" },
  "projection": { "name": 1, "email": 1, "_id": 0 }
}
Response:
{
  "document": {
    "name": "John Doe",
    "email": "user@example.com"
  }
}

2. Find Multiple Documents (POST /data/v1/action/find)

Purpose: Retrieve multiple documents from a collection Request Fields:
{
  "collection": "string",          // Required: Collection name
  "database": "string",            // Optional: Database name
  "filter": {},                    // Optional: Query filter object
  "projection": {},               // Optional: Fields to include/exclude
  "sort": {},                     // Optional: Sort specification
  "limit": 0,                     // Optional: Maximum number of documents
  "skip": 0                       // Optional: Number of documents to skip
}
Example Request:
{
  "collection": "products",
  "filter": { "category": "electronics", "price": { "$lt": 500 } },
  "projection": { "name": 1, "price": 1, "category": 1 },
  "sort": { "price": 1 },
  "limit": 10,
  "skip": 0
}
Response:
{
  "documents": [
    {
      "name": "Wireless Mouse",
      "price": 29.99,
      "category": "electronics"
    },
    {
      "name": "USB Cable",
      "price": 9.99,
      "category": "electronics"
    }
  ]
}

3. Insert One Document (POST /data/v1/action/insertOne)

Purpose: Insert a single document into a collection Request Fields:
{
  "collection": "string",          // Required: Collection name
  "database": "string",            // Optional: Database name
  "document": {}                   // Required: Document to insert
}
Example Request:
{
  "collection": "users",
  "document": {
    "name": "John Doe",
    "email": "john@example.com",
    "age": 30,
    "createdAt": "2024-01-01T00:00:00Z"
  }
}
Response:
{
  "insertedId": "507f1f77bcf86cd799439011"
}

4. Insert Multiple Documents (POST /data/v1/action/insertMany)

Purpose: Insert multiple documents into a collection Request Fields:
{
  "collection": "string",          // Required: Collection name
  "database": "string",            // Optional: Database name
  "documents": []                  // Required: Array of documents to insert
}
Example Request:
{
  "collection": "orders",
  "documents": [
    {
      "orderId": "ORD001",
      "customerId": "CUST123",
      "total": 99.99,
      "status": "pending"
    },
    {
      "orderId": "ORD002",
      "customerId": "CUST456",
      "total": 149.99,
      "status": "completed"
    }
  ]
}
Response:
{
  "insertedIds": [
    "507f1f77bcf86cd799439011",
    "507f1f77bcf86cd799439012"
  ]
}

5. Update One Document (POST /data/v1/action/updateOne)

Purpose: Update a single document in a collection Request Fields:
{
  "collection": "string",          // Required: Collection name
  "database": "string",            // Optional: Database name
  "filter": {},                    // Required: Query filter to match document
  "update": {},                    // Required: Update operations
  "upsert": false                  // Optional: Create document if not found
}
Example Request:
{
  "collection": "users",
  "filter": { "email": "john@example.com" },
  "update": {
    "$set": { "lastLogin": "2024-01-15T10:30:00Z" },
    "$inc": { "loginCount": 1 }
  },
  "upsert": false
}
Response:
{
  "matchedCount": 1,
  "modifiedCount": 1
}

6. Update Multiple Documents (POST /data/v1/action/updateMany)

Purpose: Update multiple documents in a collection Request Fields:
{
  "collection": "string",          // Required: Collection name
  "database": "string",            // Optional: Database name
  "filter": {},                    // Required: Query filter to match documents
  "update": {},                    // Required: Update operations
  "upsert": false                  // Optional: Create documents if not found
}
Example Request:
{
  "collection": "products",
  "filter": { "category": "electronics" },
  "update": {
    "$mul": { "price": 0.9 }
  },
  "upsert": false
}
Response:
{
  "matchedCount": 25,
  "modifiedCount": 25
}

7. Replace One Document (POST /data/v1/action/replaceOne)

Purpose: Replace an entire document in a collection Request Fields:
{
  "collection": "string",          // Required: Collection name
  "database": "string",            // Optional: Database name
  "filter": {},                    // Required: Query filter to match document
  "replacement": {},               // Required: New document to replace with
  "upsert": false                  // Optional: Create document if not found
}
Example Request:
{
  "collection": "users",
  "filter": { "_id": { "$oid": "507f1f77bcf86cd799439011" } },
  "replacement": {
    "name": "Jane Smith",
    "email": "jane@example.com",
    "age": 25,
    "department": "Engineering"
  },
  "upsert": false
}
Response:
{
  "matchedCount": 1,
  "modifiedCount": 1
}

8. Delete One Document (POST /data/v1/action/deleteOne)

Purpose: Delete a single document from a collection Request Fields:
{
  "collection": "string",          // Required: Collection name
  "database": "string",            // Optional: Database name
  "filter": {}                     // Required: Query filter to match document
}
Example Request:
{
  "collection": "users",
  "filter": { "email": "inactive@example.com" }
}
Response:
{
  "deletedCount": 1
}

9. Delete Multiple Documents (POST /data/v1/action/deleteMany)

Purpose: Delete multiple documents from a collection Request Fields:
{
  "collection": "string",          // Required: Collection name
  "database": "string",            // Optional: Database name
  "filter": {}                     // Required: Query filter to match documents
}
Example Request:
{
  "collection": "logs",
  "filter": {
    "timestamp": {
      "$lt": "2024-01-01T00:00:00Z"
    }
  }
}
Response:
{
  "deletedCount": 1523
}

10. Aggregate (POST /data/v1/action/aggregate)

Purpose: Perform aggregation operations on a collection Request Fields:
{
  "collection": "string",          // Required: Collection name
  "database": "string",            // Optional: Database name
  "pipeline": []                   // Required: Aggregation pipeline stages
}
Example Request:
{
  "collection": "orders",
  "pipeline": [
    {
      "$match": { "status": "completed" }
    },
    {
      "$group": {
        "_id": "$customerId",
        "totalSpent": { "$sum": "$total" },
        "orderCount": { "$sum": 1 }
      }
    },
    {
      "$sort": { "totalSpent": -1 }
    },
    {
      "$limit": 10
    }
  ]
}
Response:
{
  "documents": [
    {
      "_id": "CUST123",
      "totalSpent": 1299.97,
      "orderCount": 13
    },
    {
      "_id": "CUST456",
      "totalSpent": 899.95,
      "orderCount": 6
    }
  ]
}

11. Count Documents (POST /data/v1/action/countDocuments)

Purpose: Count the number of documents matching a filter Request Fields:
{
  "dataSource": "string",          // Required: Data source identifier
  "collection": "string",          // Required: Collection name
  "database": "string",            // Required: Database name
  "filter": {}                     // Optional: Query filter object
}
Example Request:
{
  "dataSource": "main",
  "database": "mydb",
  "collection": "users",
  "filter": { "status": "active" }
}
Response:
{
  "count": 1523
}

12. Estimated Document Count (POST /data/v1/action/estimatedDocumentCount)

Purpose: Get an estimated count of all documents in a collection (faster but less accurate than countDocuments) Request Fields:
{
  "dataSource": "string",          // Required: Data source identifier
  "collection": "string",          // Required: Collection name
  "database": "string"             // Required: Database name
}
Example Request:
{
  "dataSource": "main",
  "database": "mydb",
  "collection": "users"
}
Response:
{
  "count": 15432
}

13. Distinct (POST /data/v1/action/distinct)

Purpose: Get distinct values for a specific field across documents Request Fields:
{
  "dataSource": "string",          // Required: Data source identifier
  "collection": "string",          // Required: Collection name
  "database": "string",            // Required: Database name
  "key": "string",                 // Required: Field name to get distinct values for
  "filter": {}                     // Optional: Query filter object
}
Example Request:
{
  "dataSource": "main",
  "database": "mydb",
  "collection": "orders",
  "key": "status",
  "filter": { "year": 2024 }
}
Response:
{
  "values": ["pending", "completed", "cancelled", "refunded"]
}

14. Find One and Update (POST /data/v1/action/findOneAndUpdate)

Purpose: Find a single document and update it atomically, returning either the original or updated document Request Fields:
{
  "dataSource": "string",          // Required: Data source identifier
  "collection": "string",          // Required: Collection name
  "database": "string",            // Required: Database name
  "filter": {},                    // Required: Query filter to match document
  "update": {},                    // Required: Update operations (must contain update operators)
  "projection": {},                // Optional: Fields to include/exclude in returned document
  "sort": {},                      // Optional: Sort specification if multiple documents match
  "upsert": false,                 // Optional: Create document if not found
  "returnNewDocument": true        // Optional: Return updated document (true) or original (false)
}
Example Request:
{
  "dataSource": "main",
  "database": "mydb",
  "collection": "inventory",
  "filter": { "sku": "ABC123" },
  "update": {
    "$inc": { "quantity": -1 },
    "$set": { "lastModified": "2024-01-15T10:30:00Z" }
  },
  "returnNewDocument": true
}
Response:
{
  "document": {
    "_id": "507f1f77bcf86cd799439011",
    "sku": "ABC123",
    "quantity": 49,
    "lastModified": "2024-01-15T10:30:00Z"
  }
}

15. Find One and Replace (POST /data/v1/action/findOneAndReplace)

Purpose: Find a single document and replace it entirely, returning either the original or replacement document Request Fields:
{
  "dataSource": "string",          // Required: Data source identifier
  "collection": "string",          // Required: Collection name
  "database": "string",            // Required: Database name
  "filter": {},                    // Required: Query filter to match document
  "replacement": {},               // Required: New document (cannot contain update operators)
  "projection": {},                // Optional: Fields to include/exclude in returned document
  "sort": {},                      // Optional: Sort specification if multiple documents match
  "upsert": false,                 // Optional: Create document if not found
  "returnNewDocument": true        // Optional: Return replacement document (true) or original (false)
}
Example Request:
{
  "dataSource": "main",
  "database": "mydb",
  "collection": "profiles",
  "filter": { "userId": "user123" },
  "replacement": {
    "userId": "user123",
    "name": "Jane Doe",
    "email": "jane.doe@example.com",
    "preferences": {
      "theme": "dark",
      "notifications": true
    }
  },
  "returnNewDocument": true
}
Response:
{
  "document": {
    "_id": "507f1f77bcf86cd799439011",
    "userId": "user123",
    "name": "Jane Doe",
    "email": "jane.doe@example.com",
    "preferences": {
      "theme": "dark",
      "notifications": true
    }
  }
}

16. Find One and Delete (POST /data/v1/action/findOneAndDelete)

Purpose: Find a single document and delete it atomically, returning the deleted document Request Fields:
{
  "dataSource": "string",          // Required: Data source identifier
  "collection": "string",          // Required: Collection name
  "database": "string",            // Required: Database name
  "filter": {},                    // Required: Query filter to match document
  "projection": {},                // Optional: Fields to include/exclude in returned document
  "sort": {}                       // Optional: Sort specification if multiple documents match
}
Example Request:
{
  "dataSource": "main",
  "database": "mydb",
  "collection": "sessions",
  "filter": { "sessionId": "sess_abc123" },
  "projection": { "userId": 1, "expiredAt": 1 }
}
Response:
{
  "document": {
    "_id": "507f1f77bcf86cd799439011",
    "userId": "user456",
    "expiredAt": "2024-01-15T10:30:00Z"
  }
}

17. Bulk Write (POST /data/v1/action/bulkWrite)

Purpose: Perform multiple write operations (insert, update, replace, delete) in a single request Request Fields:
{
  "dataSource": "string",          // Required: Data source identifier
  "collection": "string",          // Required: Collection name
  "database": "string",            // Required: Database name
  "operations": [],                // Required: Array of write operations
  "ordered": true                  // Optional: Execute operations in order (default true)
}
Operation Types:
  • insertOne: { "insertOne": { "document": {...} } }
  • updateOne: { "updateOne": { "filter": {...}, "update": {...}, "upsert": false } }
  • updateMany: { "updateMany": { "filter": {...}, "update": {...}, "upsert": false } }
  • replaceOne: { "replaceOne": { "filter": {...}, "replacement": {...}, "upsert": false } }
  • deleteOne: { "deleteOne": { "filter": {...} } }
  • deleteMany: { "deleteMany": { "filter": {...} } }
Example Request:
{
  "dataSource": "main",
  "database": "mydb",
  "collection": "products",
  "operations": [
    {
      "insertOne": {
        "document": { "name": "New Product", "price": 99.99 }
      }
    },
    {
      "updateMany": {
        "filter": { "category": "electronics" },
        "update": { "$mul": { "price": 0.9 } }
      }
    },
    {
      "deleteOne": {
        "filter": { "discontinued": true }
      }
    }
  ],
  "ordered": true
}
Response:
{
  "insertedCount": 1,
  "matchedCount": 15,
  "modifiedCount": 15,
  "deletedCount": 1,
  "upsertedCount": 0,
  "upsertedIds": {}
}

18. Create Index (POST /data/v1/action/createIndex)

Purpose: Create an index on a collection to improve query performance Request Fields:
{
  "dataSource": "string",          // Required: Data source identifier
  "collection": "string",          // Required: Collection name
  "database": "string",            // Required: Database name
  "keys": {},                      // Required: Index specification (field: 1 or -1)
  "options": {}                    // Optional: Index options (name, unique, sparse, etc.)
}
Example Request:
{
  "dataSource": "main",
  "database": "mydb",
  "collection": "users",
  "keys": { "email": 1 },
  "options": {
    "name": "email_index",
    "unique": true,
    "sparse": false
  }
}
Response:
{
  "createdCollectionAutomatically": false,
  "numIndexesBefore": 1,
  "numIndexesAfter": 2,
  "ok": 1
}

19. Drop Index (POST /data/v1/action/dropIndex)

Purpose: Remove an index from a collection Request Fields:
{
  "dataSource": "string",          // Required: Data source identifier
  "collection": "string",          // Required: Collection name
  "database": "string",            // Required: Database name
  "name": "string"                 // Required: Index name to drop
}
Example Request:
{
  "dataSource": "main",
  "database": "mydb",
  "collection": "users",
  "name": "email_index"
}
Response:
{
  "nIndexesWas": 2,
  "ok": 1
}

20. List Indexes (POST /data/v1/action/listIndexes)

Purpose: List all indexes on a collection Request Fields:
{
  "dataSource": "string",          // Required: Data source identifier
  "collection": "string",          // Required: Collection name
  "database": "string"             // Required: Database name
}
Example Request:
{
  "dataSource": "main",
  "database": "mydb",
  "collection": "users"
}
Response:
{
  "indexes": [
    {
      "v": 2,
      "key": { "_id": 1 },
      "name": "_id_"
    },
    {
      "v": 2,
      "key": { "email": 1 },
      "name": "email_index",
      "unique": true
    }
  ]
}

21. List Collections (POST /data/v1/action/listCollections)

Purpose: List all collections in a database Request Fields:
{
  "dataSource": "string",          // Required: Data source identifier
  "database": "string"             // Required: Database name
}
Example Request:
{
  "dataSource": "main",
  "database": "mydb"
}
Response:
{
  "collections": [
    { "name": "users", "type": "collection" },
    { "name": "products", "type": "collection" },
    { "name": "orders", "type": "collection" }
  ]
}

22. Create Collection (POST /data/v1/action/createCollection)

Purpose: Create a new collection in a database Request Fields:
{
  "dataSource": "string",          // Required: Data source identifier
  "database": "string",            // Required: Database name
  "collection": "string"           // Required: Collection name to create
}
Example Request:
{
  "dataSource": "main",
  "database": "mydb",
  "collection": "analytics"
}
Response:
{
  "ok": 1
}

23. Drop Collection (POST /data/v1/action/dropCollection)

Purpose: Delete a collection and all its documents Request Fields:
{
  "dataSource": "string",          // Required: Data source identifier
  "database": "string",            // Required: Database name
  "collection": "string"           // Required: Collection name to drop
}
Example Request:
{
  "dataSource": "main",
  "database": "mydb",
  "collection": "temp_data"
}
Response:
{
  "ok": 1
}

24. List Databases (POST /data/v1/action/listDatabases)

Purpose: List all available databases Request Fields:
{
  "dataSource": "string"           // Required: Data source identifier
}
Example Request:
{
  "dataSource": "main"
}
Response:
{
  "databases": [
    { "name": "admin", "sizeOnDisk": 32768, "empty": false },
    { "name": "mydb", "sizeOnDisk": 8192000, "empty": false },
    { "name": "test", "sizeOnDisk": 32768, "empty": true }
  ],
  "totalSize": 8256736,
  "ok": 1
}

25. Run Command (POST /data/v1/action/runCommand)

Purpose: Execute arbitrary database commands Request Fields:
{
  "dataSource": "string",          // Required: Data source identifier
  "database": "string",            // Required: Database name
  "command": {}                    // Required: Command object
}
Example Request:
{
  "dataSource": "main",
  "database": "mydb",
  "command": {
    "dbStats": 1,
    "scale": 1024
  }
}
Response:
{
  "result": {
    "db": "mydb",
    "collections": 5,
    "views": 0,
    "objects": 1523,
    "avgObjSize": 512,
    "dataSize": 780288,
    "storageSize": 1024000,
    "ok": 1
  }
}

Quick cURL Examples

# Insert a document
curl -X POST http://localhost:3000/data/v1/action/insertOne \
  -H "Content-Type: application/json" \
  -H "apiKey: your-api-key" \
  -d '{"dataSource": "main", "database": "mydb", "collection": "users", "document": {"name": "John Doe"}}'

# Find documents
curl -X POST http://localhost:3000/data/v1/action/find \
  -H "Content-Type: application/json" \
  -H "apiKey: your-api-key" \
  -d '{"dataSource": "main", "database": "mydb", "collection": "users", "filter": {"name": "John Doe"}}'

# Update a document
curl -X POST http://localhost:3000/data/v1/action/updateOne \
  -H "Content-Type: application/json" \
  -H "apiKey: your-api-key" \
  -d '{"dataSource": "main", "database": "mydb", "collection": "users", "filter": {"name": "John Doe"}, "update": {"$set": {"active": true}}}'

# Count documents
curl -X POST http://localhost:3000/data/v1/action/countDocuments \
  -H "Content-Type: application/json" \
  -H "apiKey: your-api-key" \
  -d '{"dataSource": "main", "database": "mydb", "collection": "users", "filter": {"status": "active"}}'

# Aggregate data
curl -X POST http://localhost:3000/data/v1/action/aggregate \
  -H "Content-Type: application/json" \
  -H "apiKey: your-api-key" \
  -d '{"dataSource": "main", "database": "mydb", "collection": "orders", "pipeline": [{"$match": {"status": "completed"}}, {"$group": {"_id": "$customerId", "total": {"$sum": "$amount"}}}]}'

Security Considerations

  • API Key Authentication: All endpoints require a valid API key
  • Input Validation: Requests are validated before processing
  • Error Handling: Proper error responses without exposing sensitive information
  • Rate Limiting: Consider implementing rate limiting for production use

Use Cases

The Data API is ideal for:
  • Admin Dashboards: Building administrative interfaces for data management
  • Data Integration: Connecting external systems to your MongoDB database
  • Rapid Prototyping: Quickly testing database operations and queries
  • Analytics Tools: Building custom analytics and reporting tools
  • Mobile Apps: Providing backend API for mobile applications

Complete Example

Want to see the full working code? Check it out on GitHub:

Complete Data API Example

See the complete source code for this example on GitHub, including all endpoints and configuration.

Next Steps