RESTspec

Draft v0.7

A specification for declarative, type-safe HTTP route definitions

1. Introduction

RESTspec defines a standard structure for describing HTTP API routes in a declarative, language-agnostic way. A RESTspec definition captures the methods, paths, inputs, and outputs of an API as a single structured object. This object can then be consumed by server frameworks, client generators, documentation tools, or validation layers.

The specification is deliberately minimal. It does not prescribe a transport, serialization format, or validation library. Instead, it defines the shape of a route contract and the rules that conforming implementations must follow.

Goals

Non-Goals

2. Terminology

Term Definition
Route Schema The top-level object describing all routes in an API. Organized by method, then by path.
Route Entry A single route definition at a given method + path combination. Contains fields for payload, query parameters, and response.
Path Template A URL path containing zero or more colon-prefixed parameters (e.g. /users/:id).
Payload The request body. Only applicable to methods that carry a body (POST, PUT, PATCH, DELETE, and custom methods).
Query Params Key-value parameters appended to the URL query string.
Response The expected shape of a successful response body.
Server Binding An implementation that reads a Route Schema and registers handlers on a server framework.
Client Binding An implementation that reads a Route Schema and provides a typed interface for making HTTP requests.
Schema Object A runtime validation object (e.g. Zod schema) that can both describe and validate a type. Optional — when absent, type safety is compile-time only.

3. Route Schema

A Route Schema is a structured object with the following shape:

{
  METHOD: {
    "PATH_TEMPLATE": RouteEntry,
    "PATH_TEMPLATE": RouteEntry,
    ...
  },
  ...
}

The first level keys are HTTP methods. The second level keys are path templates. Each value is a Route Entry.

3.1 Route Entry

A Route Entry describes a single endpoint. It contains the following fields:

Field Required Availability Description
response required All methods The shape of the response body. Can be a schema object or a static type declaration.
payload optional POST, PUT, PATCH, DELETE, custom methods The shape of the request body. MUST NOT appear on GET entries.
queryParams optional All methods The shape of the URL query parameters.

3.2 Type Representations

Each field in a Route Entry can be expressed in one of two ways, depending on the implementation:

Schema Objects (runtime)

A runtime validation object that can parse and validate data. Enables both compile-time type inference and runtime validation.

// Example: Zod
{
  response: z.object({
    id: z.string(),
    name: z.string(),
  })
}

Static Types (compile-time)

A language-level type declaration. Provides compile-time type safety with zero runtime cost. No validation occurs.

// Example: TypeScript type
{
  response: {
    id: string
    name: string
  }
}
Implementer note: A conforming implementation MUST support at least one of these representations. Supporting both is RECOMMENDED.

3.3 Full Example

{
  GET: {
    "/users": {
      queryParams: { page: number, limit: number },
      response:    { items: User[], total: number }
    },
    "/users/:id": {
      response: { id: string, name: string, email: string }
    }
  },
  POST: {
    "/users": {
      payload:  { name: string, email: string },
      response: { id: string }
    }
  },
  DELETE: {
    "/users/:id": {
      response: void
    }
  }
}

4. HTTP Methods

RESTspec defines the following standard methods. Implementations MAY support additional custom methods.

Method Has Payload Description
GET No Retrieve a resource. MUST NOT include a payload field.
POST Yes Create a resource or trigger an action.
PUT Yes Replace a resource entirely.
PATCH Yes Partially update a resource.
DELETE Yes Remove a resource. Payload is optional but permitted.

4.1 Custom Methods

Implementations MAY support custom HTTP methods (e.g. QUERY) as top-level keys in the Route Schema. Custom methods follow the same Route Entry structure as standard methods and carry a payload by default.

When a server binding encounters a custom method, it SHOULD register a catch-all handler for the path and reject requests whose HTTP method does not match. The RECOMMENDED rejection status is 405 Method Not Allowed.

5. Path Parameters

Path parameters are defined using colon-prefixed segments within path templates.

5.1 Syntax

A parameter segment begins with : followed by an identifier: /resource/:paramName. Multiple parameters may appear in a single path.

Path Template Extracted Parameters
/users/:id { id: string }
/orgs/:orgId/members/:memberId { orgId: string, memberId: string }
/health (none)

5.2 Rules

5.3 Substitution

Client bindings MUST replace each :param segment with the corresponding value before making a request. If a required parameter is missing, the client MUST throw an error.

// Template:  /orgs/:orgId/members/:memberId
// Params:    { orgId: "acme", memberId: "42" }
// Result:    /orgs/acme/members/42

5.4 Server Access

Server bindings MUST expose path parameter values to handlers. The mechanism is framework-specific (e.g. req.params in Express, c.req.param() in Hono).

6. Request Format

A conforming client MUST construct requests as follows:

6.1 URL Construction

  1. Start with the base URL.
  2. Append the path template after substituting all path parameters.
  3. If queryParams are provided, serialize them as a URL query string and append.

6.2 Body Serialization

6.3 Headers

Implementations SHOULD provide a mechanism for injecting custom headers (e.g. authorization tokens) into every request. The header provider MAY be synchronous or asynchronous.

7. Response Format

7.1 Success Responses

7.2 Void Responses

When the response type is void (or equivalent), the client SHOULD NOT attempt to parse the response body and SHOULD return undefined (or the language equivalent).

7.3 Error Responses

A response with a non-2xx status code is considered an error. The client SHOULD attempt to parse the error body as JSON and surface the error message.

8. Known Implementations

Library Language Server Client
@jokio/rpc TypeScript Express fetch