proposal

Non-REST & RPC

This is a proposal. Where REST conventions don't fit, the engine lets you say exactly what an endpoint does - verbs in the path, methods used however the real service uses them, and a raw-query escape hatch for the rest.

Verbs in the path

RPC-style and action endpoints name the operation in the URL. The HTTP method is whatever the real service chose; the operation: says what actually happens.

- path: /users/:guid/deactivate
  method: POST
  operation: update          # not "create" - the method doesn't decide
  key: guid
  response: { schema: User }

- path: /rpc/getUser
  method: POST               # an RPC call that reads
  operation: get
  key: guid                  # bound from the request body
  response: { schema: User }

A POST that deletes

Plenty of real APIs delete via POST (or never expose DELETE at all). That's a one-line override:

- path: /users/:guid/remove
  method: POST
  operation: delete
  key: guid
  response: { schema: User }
  status: 204

Custom operations

Some actions aren't CRUD at all - counters, toggles, bulk jobs. The proposed operation: query with an inline statement is the escape hatch when the structured operations can't express the behavior.

Inline custom queries

A parameterized SQL statement, with placeholders bound from path parameters, the request body, and the query string:

- path: /users/:guid/posts
  method: GET
  operation: query
  query: |
    SELECT * FROM posts WHERE authorGuid = :guid AND published = 1
  response: { type: array, schema: Post }

This is deliberately the trapdoor, not the front door - reach for it only when the declarative model falls short.

Open questions