Filter by title

Custom Endpoints

Custom Endpoints allow you to define REST API routes with server-side JavaScript handlers directly in model.json. Each endpoint is registered as an ASP.NET Core endpoint at startup and supports hot-reload when the model changes.

Defining Endpoints

Add endpoints to the endpoints array in model.json:

{
  "endpoints": [
    {
      "name": "GetProductStats",
      "route": "/api/custom/products/stats",
      "method": "GET",
      "description": "Get product statistics",
      "requireAuthentication": false,
      "javascript": "var count = await db.count('LowCodeDemo.Products.Product');\nreturn ok({ totalProducts: count });"
    }
  ]
}

Endpoint Descriptor

Field Type Default Description
name string Required Unique endpoint name
route string Required URL route pattern (supports {parameters})
method string "GET" HTTP method: GET, POST, PUT, DELETE
javascript string Required JavaScript handler code
description string null Description for documentation
requireAuthentication bool true Require authenticated user
requiredPermissions string[] null Required permission names

Route Parameters

Use {paramName} syntax in the route. Access values via the route object:

{
  "name": "GetProductById",
  "route": "/api/custom/products/{id}",
  "method": "GET",
  "javascript": "var product = await db.get('LowCodeDemo.Products.Product', route.id);\nif (!product) { return notFound('Product not found'); }\nreturn ok({ id: product.Id, name: product.Name, price: product.Price });"
}

JavaScript Context

Inside custom endpoint scripts, you have access to:

Request Context

Variable Description
request Full request object
route Route parameter values (e.g., route.id)
params Alias for route parameters
query Query string parameters (e.g., query.q, query.page)
body Request body (for POST/PUT)
headers Request headers
user Current user (same as context.currentUser in Interceptors)
email Email sender (same as context.emailSender in Interceptors)

Response Helpers

Function HTTP Status Description
ok(data) 200 Success response with data
created(data) 201 Created response with data
noContent() 204 No content response
badRequest(message) 400 Bad request response
unauthorized(message) 401 Unauthorized response
forbidden(message) 403 Forbidden response
notFound(message) 404 Not found response
error(message) 500 Internal server error response
response(statusCode, data, error) Custom Custom status code response

Logging

Function Description
log(message) Log an informational message
logWarning(message) Log a warning message
logError(message) Log an error message

Database API

The full Scripting API (db object) is available for querying and mutating data.

Examples

Get Statistics

{
  "name": "GetProductStats",
  "route": "/api/custom/products/stats",
  "method": "GET",
  "requireAuthentication": false,
  "javascript": "var totalCount = await db.count('LowCodeDemo.Products.Product');\nvar productTable = await db.query('LowCodeDemo.Products.Product');\nvar avgPrice = totalCount > 0 ? await productTable.average(p => p.Price) : 0;\nreturn ok({ totalProducts: totalCount, averagePrice: avgPrice });"
}

Search with Query Parameters

{
  "name": "SearchCustomers",
  "route": "/api/custom/customers/search",
  "method": "GET",
  "requireAuthentication": true,
  "javascript": "var searchTerm = query.q || '';\nvar customerTable = await db.query('LowCodeDemo.Customers.Customer');\nvar customers = await customerTable\n  .where(c => c.Name.toLowerCase().includes(searchTerm.toLowerCase()))\n  .take(10)\n  .toList();\nreturn ok(customers.map(c => ({ id: c.Id, name: c.Name, email: c.EmailAddress })));"
}

Dashboard Summary

{
  "name": "GetDashboardSummary",
  "route": "/api/custom/dashboard",
  "method": "GET",
  "requireAuthentication": true,
  "javascript": "var productCount = await db.count('LowCodeDemo.Products.Product');\nvar customerCount = await db.count('LowCodeDemo.Customers.Customer');\nvar orderCount = await db.count('LowCodeDemo.Orders.Order');\nreturn ok({ products: productCount, customers: customerCount, orders: orderCount, user: user.isAuthenticated ? user.userName : 'Anonymous' });"
}

Authentication and Authorization

Setting Behavior
requireAuthentication: false Endpoint is publicly accessible
requireAuthentication: true User must be authenticated
requiredPermissions: ["MyApp.Products"] User must have the specified permissions

See Also

Contributors


Last updated: March 05, 2026 Edit this page on GitHub

Was this page helpful?

Please make a selection.

To help us improve, please share your reason for the negative feedback in the field below.

Please enter a note.

Thank you for your valuable feedback!

Please note that although we cannot respond to feedback, our team will use your comments to improve the experience.

ABP Community Talks
ABP Meets Angular SSR: Building Fast, Scalable Enterprise Apps
12 Feb, 17:00
Online
Watch the Event
ABP Live Webinar
Webinar Calendar Webinar Calendar
Discover
ABP Platform
Register Now
Mar 11
Wednesday,
17:00 UTC
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.