ObjectOS LogoObjectOS

HTTP Protocol Specification

The ObjectOS Server exposes a RESTful HTTP API that provides complete CRUD operations for all objects defined in metadata. This document specifies the complete HTTP protocol.

Base URL

http://localhost:5320/api/v1
  • Development: ObjectStack serves at port 5320 (objectstack serve --port 5320)
  • Admin Console: Vite dev server at port 5321, proxies /api/v1:5320
  • Production/Vercel: Same-origin (/api/v1)

Authentication

Session-Based Auth (Better-Auth)

ObjectOS uses Better-Auth for authentication with session cookies. All auth routes are under /api/v1/auth/*:

POST /api/v1/auth/sign-up/email
Content-Type: application/json

{
  "name": "John Doe",
  "email": "user@example.com",
  "password": "securepassword"
}
POST /api/v1/auth/sign-in/email
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "securepassword"
}

Sessions are managed via HTTP-only cookies (set by Better-Auth). No manual Authorization header is required for browser clients.


## Request Headers

### Required Headers

Content-Type: application/json


### Optional Headers

```text
Authorization: Bearer <token>      # For authenticated requests
X-Request-ID: <unique_id>          # For request tracking
Accept-Language: en-US             # For internationalization

Response Format

Success Response

All successful responses follow this structure:

{
  "success": true,
  "data": {
    // Response data
  },
  "meta": {
    "count": 100, // Total records (for queries)
    "page": 1, // Current page
    "limit": 20 // Records per page
  }
}

Error Response

All error responses follow this structure:

{
  "success": false,
  "error": {
    "code": 400,
    "message": "Validation failed",
    "details": {
      "field": "email",
      "reason": "Email is required"
    }
  }
}

HTTP Status Codes

CodeMeaningDescription
200OKRequest succeeded
201CreatedResource created successfully
400Bad RequestInvalid request syntax or validation error
401UnauthorizedAuthentication required
403ForbiddenInsufficient permissions
404Not FoundResource not found
409ConflictUnique constraint violation
422Unprocessable EntityBusiness logic validation failed
500Internal Server ErrorServer error

Standard Endpoints

1. Query Records

Retrieve multiple records with filtering, sorting, and pagination.

Endpoint:

POST /api/data/{object}/query

Request Body:

{
  "filters": {
    "status": "active"
  },
  "fields": ["id", "name", "email"],
  "sort": [{ "field": "created_at", "order": "desc" }],
  "limit": 20,
  "skip": 0
}

Response:

{
  "success": true,
  "data": [
    {
      "id": "contact_123",
      "name": "John Doe",
      "email": "john@example.com"
    }
  ],
  "meta": {
    "count": 150,
    "limit": 20,
    "skip": 0
  }
}

Example:

curl -X POST http://localhost:5320/api/v1/data/contacts/query \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "filters": { "status": "active" },
    "limit": 20
  }'

2. Get Single Record

Retrieve a single record by ID.

Endpoint:

GET /api/data/{object}/{id}

Query Parameters:

  • fields: Comma-separated list of fields to return
  • include: Comma-separated list of related objects to include

Response:

{
  "success": true,
  "data": {
    "id": "contact_123",
    "first_name": "John",
    "last_name": "Doe",
    "email": "john@example.com",
    "created_at": "2024-01-15T10:30:00Z"
  }
}

Example:

curl -X GET http://localhost:5320/api/v1/data/contacts/contact_123 \
  -H "Authorization: Bearer <token>"

3. Create Record

Create a new record.

Endpoint:

POST /api/data/{object}

Request Body:

{
  "first_name": "Jane",
  "last_name": "Smith",
  "email": "jane@example.com",
  "phone": "+1234567890"
}

Response (201 Created):

{
  "success": true,
  "data": {
    "id": "contact_456",
    "first_name": "Jane",
    "last_name": "Smith",
    "email": "jane@example.com",
    "phone": "+1234567890",
    "created_at": "2024-01-15T11:00:00Z",
    "updated_at": "2024-01-15T11:00:00Z"
  }
}

Example:

curl -X POST http://localhost:5320/api/v1/data/contacts \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "first_name": "Jane",
    "last_name": "Smith",
    "email": "jane@example.com"
  }'

4. Update Record

Update an existing record.

Endpoint:

PATCH /api/data/{object}/{id}

Request Body:

{
  "phone": "+1987654321",
  "status": "inactive"
}

Response:

{
  "success": true,
  "data": {
    "id": "contact_123",
    "first_name": "John",
    "last_name": "Doe",
    "email": "john@example.com",
    "phone": "+1987654321",
    "status": "inactive",
    "updated_at": "2024-01-15T11:30:00Z"
  }
}

Example:

curl -X PATCH http://localhost:5320/api/v1/data/contacts/contact_123 \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{
    "phone": "+1987654321"
  }'

5. Delete Record

Delete a record.

Endpoint:

DELETE /api/data/{object}/{id}

Response (200 OK):

{
  "success": true,
  "data": {
    "id": "contact_123",
    "deleted": true
  }
}

Example:

curl -X DELETE http://localhost:5320/api/v1/data/contacts/contact_123 \
  -H "Authorization: Bearer <token>"

6. Batch Operations

Create, update, or delete multiple records in a single request.

Endpoint:

POST /api/data/{object}/batch

Request Body:

{
  "operations": [
    {
      "type": "create",
      "data": { "name": "Record 1" }
    },
    {
      "type": "update",
      "id": "contact_123",
      "data": { "status": "active" }
    },
    {
      "type": "delete",
      "id": "contact_456"
    }
  ]
}

Response:

{
  "success": true,
  "data": {
    "created": 1,
    "updated": 1,
    "deleted": 1,
    "results": [
      { "type": "create", "id": "contact_789", "success": true },
      { "type": "update", "id": "contact_123", "success": true },
      { "type": "delete", "id": "contact_456", "success": true }
    ]
  }
}

Metadata Endpoints

Get Object Metadata

Retrieve metadata definition for an object.

Endpoint:

GET /api/metadata/{object}

Response:

{
  "success": true,
  "data": {
    "name": "contacts",
    "label": "Contact",
    "icon": "user",
    "fields": {
      "first_name": {
        "type": "text",
        "label": "First Name",
        "required": true
      },
      "email": {
        "type": "email",
        "label": "Email",
        "unique": true
      }
    },
    "permission_set": {
      "allowRead": true,
      "allowCreate": ["sales", "admin"],
      "allowEdit": ["sales", "admin"],
      "allowDelete": ["admin"]
    }
  }
}

List All Objects

Get list of all available objects.

Endpoint:

GET /api/metadata

Response:

{
  "success": true,
  "data": [
    {
      "name": "contacts",
      "label": "Contact",
      "icon": "user"
    },
    {
      "name": "accounts",
      "label": "Account",
      "icon": "building"
    }
  ]
}

Advanced Features

Filtering

See Query Language Specification for complete filter syntax.

curl -X POST http://localhost:5320/api/v1/data/contacts/query \
  -H "Content-Type: application/json" \
  -d '{
    "filters": {
      "$and": [
        { "status": "active" },
        { "age": { "$gte": 18 } }
      ]
    }
  }'

Include related object data in a single request:

curl -X POST http://localhost:5320/api/v1/data/opportunities/query \
  -H "Content-Type: application/json" \
  -d '{
    "include": ["account", "owner"],
    "limit": 10
  }'

Response includes nested objects:

{
  "data": [
    {
      "id": "opp_123",
      "name": "Big Deal",
      "account": {
        "id": "acc_456",
        "name": "Acme Corp"
      },
      "owner": {
        "id": "user_789",
        "name": "John Doe"
      }
    }
  ]
}

Pagination

Use limit and skip for pagination:

# Page 1
curl -X POST http://localhost:5320/api/v1/data/contacts/query \
  -d '{ "limit": 20, "skip": 0 }'

# Page 2
curl -X POST http://localhost:5320/api/v1/data/contacts/query \
  -d '{ "limit": 20, "skip": 20 }'

# Page 3
curl -X POST http://localhost:5320/api/v1/data/contacts/query \
  -d '{ "limit": 20, "skip": 40 }'

Error Examples

400 Bad Request - Validation Error

{
  "success": false,
  "error": {
    "code": 400,
    "message": "Validation failed",
    "details": {
      "email": "Email is required"
    }
  }
}

401 Unauthorized

{
  "success": false,
  "error": {
    "code": 401,
    "message": "Authentication required"
  }
}

403 Forbidden

{
  "success": false,
  "error": {
    "code": 403,
    "message": "Insufficient permissions",
    "details": {
      "action": "delete",
      "object": "contacts"
    }
  }
}

404 Not Found

{
  "success": false,
  "error": {
    "code": 404,
    "message": "Record not found",
    "details": {
      "object": "contacts",
      "id": "contact_999"
    }
  }
}

409 Conflict - Unique Constraint

{
  "success": false,
  "error": {
    "code": 409,
    "message": "Unique constraint violation",
    "details": {
      "field": "email",
      "value": "john@example.com"
    }
  }
}

Rate Limiting

API requests are rate-limited per user:

  • Free tier: 100 requests per minute
  • Pro tier: 1000 requests per minute

Rate limit headers are included in responses:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1642341600

CORS

Cross-Origin Resource Sharing (CORS) is configured in objectstack.config.ts:

  • http://localhost:5321 (Vite dev server)
  • http://localhost:5320 (ObjectStack server)
  • Additional origins via CORS_ORIGINS environment variable (CSV)

WebSocket Protocol

ObjectOS provides real-time updates via @objectos/realtime WebSocket plugin:

Endpoint:

ws://localhost:5320/ws

Subscribe to changes:

{
  "type": "subscribe",
  "channel": "data.contacts",
  "filters": { "status": "active" }
}

Presence and awareness (cursor tracking, collaborative editing) are supported via the awareness protocol. See the @objectos/realtime package for full documentation.

API Versioning

Current API version: v1

Version is included in the URL path:

/api/v1/data/{object}

Breaking changes will introduce new versions (v2, v3, etc.).

Edit this page on GitHub

On this page