Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
objectstack-ai avatar

Objectstack Api

  • 132 installs
  • 18 repo stars
  • Updated August 5, 2026
  • objectstack-ai/framework

Helps with backend & apis tasks.

About

objectstack-api is a Claude Code skill for backend & apis. It helps solo builders move faster with AI-assisted development.

  • objectstack-api
  • Backend & APIs
  • AI-coding skill

Objectstack Api by the numbers

  • 132 all-time installs (skills.sh)
  • +4 installs in the week ending Aug 4, 2026 (Skillselion tracking)
  • Ranked #2,693 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/objectstack-ai/framework --skill objectstack-api

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs132
repo stars18
Last updatedAugust 5, 2026
Repositoryobjectstack-ai/framework

What it does

Helps with backend & apis tasks.

Files

SKILL.mdMarkdownGitHub ↗

API Design — ObjectStack API Protocol

Expert instructions for designing REST APIs, service contracts, and integration protocols using the ObjectStack specification. This skill covers endpoint definitions, API discovery, authentication, dispatcher configuration, and inter-service communication patterns.

---

When to Use This Skill

  • You are defining custom REST API endpoints beyond auto-generated CRUD.
  • You need to configure API authentication and authorization.
  • You are setting up service discovery and health checks.
  • You are designing inter-service communication (service-to-service calls).
  • You need to understand the dispatcher routing system.
  • You are integrating external APIs via datasource connectors.

---

Auto-Generated vs Custom APIs

Auto-Generated APIs

Every ObjectStack object with apiEnabled: true (the default) automatically gets a full REST API:

GET    /api/v1/{object}          # List records (with filter, sort, pagination)
GET    /api/v1/{object}/:id      # Get single record
POST   /api/v1/{object}          # Create record
PATCH  /api/v1/{object}/:id      # Update record
DELETE /api/v1/{object}/:id      # Delete record (soft-delete if trash enabled)
POST   /api/v1/{object}/bulk     # Bulk operations
GET    /api/v1/{object}/aggregate # Aggregation queries
Key rule: If your object defines apiMethods, only those operations are
exposed. For example, apiMethods: ['get', 'list'] creates a read-only API.

Metadata API (/meta)

The metadata read surface lives under /api/v1/meta (separate from the data CRUD routes above):

GET /api/v1/meta/:type            # List metadata items of a type (object, view, flow, doc, …)
GET /api/v1/meta/:type/:name      # Read a single metadata item

Three query-param contracts gained in 9.x:

  • `?preview=draft` (#1763) — overlay pending draft metadata instead of the

published copy, on both list and get. The draft path is cache-bypassed, so it always reflects the latest unpublished edit (ADR-0033/0037 authoring loop).

  • `?package=<packageId>` (ADR-0048, #1816/#1819) — package-scope a read so

two installed packages that share a bare metadata name disambiguate by owning package; prefer-local resolution. A package-scoped read bypasses the meta cache. The layered / Studio-editor read is package-scoped the same way.

  • `/meta/doc` (ADR-0046, #1790) — docs-as-metadata. The list response omits

each doc's content by default (use ?include=content to include it); the single-item GET /meta/doc/:name always returns the full body.

Public (anonymous) Form Endpoints

Any FormView declared with sharing.allowAnonymous: true and a publicLink slug is auto-mounted at:

GET  /api/v1/forms/:slug         # returns form spec + restricted objectSchema
POST /api/v1/forms/:slug/submit  # whitelist-filtered INSERT, no auth header

These bypass enforceAuth, run under a synthetic { permissions: ['guest_portal'], anonymous: true } execution context, and are intended for Web-to-Lead / Web-to-Case style flows. The framework strips fields outside the form's sections[].fields[] list; a beforeInsert hook on the target object should stamp safe defaults (status='new', lead_source='web', …) and delete privileged keys (owner, internal_notes, …). See content/docs/guides/public-forms.mdx for the full contract.

Custom Endpoints

For business logic beyond CRUD, define custom endpoints via the REST API plugin:

{
  name: 'close_case',
  path: '/api/v1/cases/:id/close',
  method: 'POST',
  description: 'Close a support case with resolution notes.',
  handlerStatus: 'implemented',
  request: {
    params: { id: { type: 'string', required: true } },
    body: {
      resolution: { type: 'string', required: true },
      satisfaction: { type: 'number', min: 1, max: 5 },
    },
  },
  response: {
    200: { description: 'Case closed successfully', schema: 'SupportCase' },
    404: { description: 'Case not found' },
    409: { description: 'Case already closed' },
  },
  auth: { required: true, permissions: ['support_agent'] },
}

---

Endpoint Naming Conventions

PatternUse CaseExample
/api/v1/{object}Auto-generated collection/api/v1/accounts
/api/v1/{object}/:idAuto-generated record/api/v1/accounts/abc123
/api/v1/{object}/:id/{action}Custom action on record/api/v1/cases/:id/close
/api/v1/{domain}/{action}Domain-level action/api/v1/ai/chat

Rules:

  • Always use plural nouns for collection paths (accounts, not account).
  • Use snake_case for multi-word paths (project_tasks, not projectTasks).
  • Use verbs only for actions, not for CRUD (/close, /approve).
  • Always prefix with /api/v1/ for versioning.

---

API Methods (Operations)

The full set of operations an object can expose:

MethodHTTPPurpose
getGET /:idRetrieve a single record
listGET /List records with filter/sort/pagination
createPOST /Create a new record
updatePATCH /:idUpdate an existing record
deleteDELETE /:idDelete a record
upsertPUT /Create or update by external ID
bulkPOST /bulkBatch create/update/delete
aggregateGET /aggregateCount, sum, avg, min, max
historyGET /:id/historyAudit trail access
searchGET /searchFull-text search
restorePOST /:id/restoreRestore from trash
purgeDELETE /:id/purgePermanent deletion
importPOST /importBulk data import
exportGET /exportData export

---

Service Discovery

ObjectStack services register themselves with the kernel and expose discovery metadata.

Service Info Schema

{
  name: 'service-rest-api',
  version: '1.0.0',
  status: 'healthy',       // 'healthy' | 'degraded' | 'unhealthy' | 'registered'
  handlerReady: true,       // HTTP handler verified and operational
  endpoints: [
    { path: '/api/v1/accounts', methods: ['GET', 'POST'] },
    { path: '/api/v1/accounts/:id', methods: ['GET', 'PATCH', 'DELETE'] },
  ],
}

Health Endpoint

Every ObjectStack deployment exposes /health:

{
  "status": "healthy",
  "version": "4.0.1",
  "services": {
    "objectql": { "status": "healthy" },
    "rest-api": { "status": "healthy" },
    "auth": { "status": "healthy" }
  }
}

---

Dispatcher & Routing

The HttpDispatcher is the central request router in ObjectStack.

Dispatcher Error Codes

HTTP StatusError TypeWhen
404ROUTE_NOT_FOUNDNo route matches the path
405METHOD_NOT_ALLOWEDRoute exists but method not supported
501NOT_IMPLEMENTEDRoute declared but handler is a stub
503SERVICE_UNAVAILABLEService is registered but not ready

Handler Status

Every endpoint has a handler status:

StatusMeaning
implementedHandler is fully functional
stubHandler exists but returns mock data
plannedHandler is defined in the spec but not yet coded
Best practice: Always set handlerStatus explicitly. The dispatcher
returns 501 NOT_IMPLEMENTED for stub and planned handlers, giving
clear feedback to API consumers.

---

Authentication & Authorization

Auth Configuration

{
  auth: {
    required: true,            // Require authentication
    permissions: ['admin'],    // Required permission profiles
    rateLimit: {
      requests: 100,
      window: '1m',           // per minute
    },
  },
}

Security Layers

LayerScopeDescription
AuthenticationRequestWho is the caller? (JWT, API key, OAuth)
RBACObjectRole-based access control (profile → permissions)
RLSRecordRow-level security (visibility rules per record)
FLSFieldField-level security (hide/mask sensitive fields)
Key rule: RBAC controls what objects/operations a user can access.
RLS controls which records within those objects are visible. FLS controls
which fields are readable/writable.

---

Datasource Configuration

Connect to external data sources for virtualised data access:

{
  name: 'legacy_erp',
  type: 'sql',
  driver: 'postgresql',
  connection: {
    host: 'erp.internal.example.com',
    port: 5432,
    database: 'erp_production',
    ssl: true,
  },
  readOnly: true,      // Safety for legacy systems
}

Supported Drivers

DriverUse Case
postgresqlPrimary production database
mysqlLegacy systems, WordPress integration
sqliteLocal development, embedded apps
tursoEdge SQLite (Turso/libSQL) — serverless
memoryUnit tests, development

---

Inter-Service Communication

Service Contracts

ObjectStack uses typed service contracts defined in @objectstack/spec/contracts:

// Service contract interface
interface DataService {
  find(object: string, query: QueryOptions): Promise<Record[]>;
  findOne(object: string, id: string): Promise<Record>;
  create(object: string, data: object): Promise<Record>;
  update(object: string, id: string, data: object): Promise<Record>;
  delete(object: string, id: string): Promise<void>;
}

Kernel Service Resolution

Services are resolved through the microkernel:

const dataService = kernel.resolve<DataService>('data');
const authService = kernel.resolve<AuthService>('auth');
const aiService = kernel.resolve<AIService>('ai');

---

Best Practices

1. Version your APIs — always use /api/v1/ prefix. Breaking changes get a new version (v2). 2. Use auto-generated APIs whenever possible. Only create custom endpoints for business logic that cannot be expressed through CRUD + triggers. 3. Return consistent error shapes. Use the DispatcherErrorResponseSchema format with type, message, and hint. 4. Document every endpoint with description and response schemas. 5. Set `handlerStatus` to communicate implementation progress to consumers. 6. Apply least-privilege auth. Every endpoint should declare its required permissions explicitly. 7. Use `upsert` for idempotent writes. External integrations should prefer upsert over create to avoid duplicates.

---

Common Pitfalls

1. Exposing internal fields via API. Use FLS (field-level security) or explicit apiMethods to restrict what is visible. 2. Missing pagination. Always paginate list endpoints. Default page size should be 20–50, with a max of 200. 3. Not handling 409 Conflict. Concurrent updates should use optimistic locking (version field) and return 409 on conflict. 4. Ignoring rate limiting. Always configure rate limits for public and external-facing APIs. 5. Using `DELETE` for soft-delete. ObjectStack DELETE performs soft-delete when trash: true is enabled on the object. Do not implement soft-delete logic in custom endpoints — use the built-in mechanism.

---

Verify your work

After adding a *.endpoint.ts, a custom route, or an auth provider, run the author-time gate before reporting done:

os validate     # Zod schema + CEL predicate validation + bindings (no artifact)
# or: os build  # the same gates, plus emits dist/

Route-guard and auth predicates are CEL; the gate parses them and fails non-zero with a located message instead of letting a malformed guard fall through at runtime. In a scaffolded project the gate is npm run validate. See objectstack-platform → Verify your work for the full gate list.

---

References

See references/_index.md for the full list of Zod schemas (with one-line descriptions) — pointers into node_modules/@objectstack/spec/src/. Always Read the source for exact field shapes; do not rely on memory of property names.

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.