Interacting with Nile

Nile exposes a single HTTP endpoint for all interactions. All requests are POST requests with a JSON body that specifies the intent, service, action, and payload.

While you can interact with Nile using raw HTTP requests, we recommend using the @nilejs/client package for a better developer experience, type-safety, and graceful error handling.

bun add @nilejs/client
import { createNileClient } from "@nilejs/client";
import type { ServicePayloads } from "./generated/types";

const nile = createNileClient<ServicePayloads>({ baseUrl: "/api" });

const { error, data } = await nile.invoke({
  service: "tasks",
  action: "create",
  payload: { title: "Buy milk" }
});

See the Client guide for the full API reference.

The Single Endpoint

POST {baseUrl}/services

The default base URL is /api, so the full endpoint is typically:

POST /api/services

Request Format

Every request follows this structure:

{
  "intent": "explore" | "execute" | "schema",
  "service": "serviceName",
  "action": "actionName",
  "payload": { ... }
}
FieldTypeDescription
intentstringWhat you want to do: explore, execute, or schema
servicestringThe service name, or "*" for wildcard
actionstringThe action name, or "*" for wildcard
payloadobjectThe input data for the action

Intents

1. Execute (intent: "execute")

Execute an action. This is the most common intent for running your business logic. In the Nile Client, this is called via nile.invoke().

curl -X POST http://localhost:8000/api/services \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "execute",
    "service": "tasks",
    "action": "create",
    "payload": { "title": "Buy milk", "status": "pending" }
  }'

Response:

{
  "status": true,
  "message": "Action 'tasks.create' executed",
  "data": {
    "task": {
      "id": "abc-123",
      "title": "Buy milk",
      "status": "pending"
    }
  }
}

2. Explore (intent: "explore")

Discover available services and actions. Use wildcards to explore.

List all services:

curl -X POST http://localhost:8000/api/services \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "explore",
    "service": "*",
    "action": "*",
    "payload": {}
  }'

Response:

{
  "status": true,
  "message": "Available services",
  "data": [
    {
      "name": "tasks",
      "description": "Task management operations",
      "meta": { "version": "1.0.0" },
      "actions": ["create", "list", "get", "update", "delete"]
    },
    {
      "name": "auth",
      "description": "Authentication service",
      "actions": ["login", "logout", "register"]
    }
  ]
}

List all actions in a service:

curl -X POST http://localhost:8000/api/services \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "explore",
    "service": "tasks",
    "action": "*",
    "payload": {}
  }'

Response:

{
  "status": true,
  "message": "Actions for 'tasks'",
  "data": [
    {
      "name": "create",
      "description": "Create a new task",
      "isProtected": false,
      "validation": true,
      "accessControl": []
    },
    {
      "name": "list",
      "description": "List all tasks",
      "isProtected": false,
      "validation": false,
      "accessControl": []
    },
    {
      "name": "get",
      "description": "Get a task by ID",
      "isProtected": true,
      "validation": true,
      "accessControl": []
    }
  ]
}

Get details of a specific action:

curl -X POST http://localhost:8000/api/services \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "explore",
    "service": "tasks",
    "action": "create",
    "payload": {}
  }'

Response:

{
  "status": true,
  "message": "Details for 'tasks.create'",
  "data": {
    "name": "create",
    "description": "Create a new task",
    "isProtected": false,
    "accessControl": null,
    "hooks": {
      "before": [],
      "after": []
    },
    "meta": null
  }
}

3. Schema (intent: "schema")

Get the Zod validation schemas as JSON Schema. Useful for generating type-safe clients.

Get all schemas:

curl -X POST http://localhost:8000/api/services \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "schema",
    "service": "*",
    "action": "*",
    "payload": {}
  }'

Response:

{
  "status": true,
  "message": "All service schemas",
  "data": {
    "tasks": {
      "create": {
        "type": "object",
        "properties": {
          "title": { "type": "string", "minLength": 1 },
          "status": { "type": "string", "enum": ["pending", "in-progress", "done"] }
        },
        "required": ["title"]
      },
      "list": null,
      "get": {
        "type": "object",
        "properties": {
          "id": { "type": "string" }
        },
        "required": ["id"]
      }
    },
    "auth": {
      "login": {
        "type": "object",
        "properties": {
          "email": { "type": "string", "format": "email" },
          "password": { "type": "string" }
        },
        "required": ["email", "password"]
      }
    }
  }
}

Get schemas for a specific service:

curl -X POST http://localhost:8000/api/services \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "schema",
    "service": "tasks",
    "action": "*",
    "payload": {}
  }'

Response:

{
  "status": true,
  "message": "Schemas for 'tasks'",
  "data": {
    "create": {
      "type": "object",
      "properties": {
        "title": { "type": "string", "minLength": 1 },
        "status": { "type": "string", "enum": ["pending", "in-progress", "done"] }
      },
      "required": ["title"]
    },
    "list": null,
    "get": {
      "type": "object",
      "properties": {
        "id": { "type": "string" }
      },
      "required": ["id"]
    }
  }
}

Get schema for a specific action:

curl -X POST http://localhost:8000/api/services \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "schema",
    "service": "tasks",
    "action": "create",
    "payload": {}
  }'

Response:

{
  "status": true,
  "message": "Schema for 'tasks.create'",
  "data": {
    "create": {
      "type": "object",
      "properties": {
        "title": { "type": "string", "minLength": 1 },
        "status": { "type": "string", "enum": ["pending", "in-progress", "done"] }
      },
      "required": ["title"]
    }
  }
}

Response Format

All responses follow a consistent structure:

{
  status: boolean;       // true for success, false for error
  message: string;      // human-readable message
  data: {               // the actual response data
    error_id?: string;  // present on errors
    [key: string]: any;
  }
}

Success response:

{
  "status": true,
  "message": "Action executed successfully",
  "data": { ... }
}

Error response:

{
  "status": false,
  "message": "Validation failed: Title is required",
  "data": {}
}

Error Handling

Nile uses a Result pattern internally. All errors are returned in the response without throwing HTTP exceptions:

HTTP StatusMeaning
200Success
400Bad request (invalid JSON, missing fields, validation errors)
404Service or action not found

Health Check

If enabled in config, you can check server health:

GET /status
{
  "status": true,
  "message": "my-app is running",
  "data": {}
}