Version: 0.1.0
RQL (Resource Query Language) is a JSON-based protocol for querying data. This document specifies the wire format for requests and responses.
| Endpoint | Method | Description |
|---|---|---|
/ or /data |
POST | Execute RQL queries |
/schema |
GET | Discover groups and ungrouped contracts |
/schema/all |
GET | Get all contracts as flat list |
/schema/:groupName |
GET | Get contracts in a specific group |
| Param | Default | Description |
|---|---|---|
pretty |
0 |
Pretty-print JSON with indentation |
raw |
0 |
Return raw Zod schemas instead of JSON Schema |
interface RQLPayload {
[queryKey: string]: RQLQuery;
}
interface RQLQuery {
contract: string; // Contract name to execute
params?: Record<string, any>; // Input parameters
select: RQLSelectObject; // Fields to return
}
interface RQLSelectObject {
[fieldName: string]: true | { select: RQLSelectObject };
}{
"product": {
"contract": "getProductDetail",
"params": { "productId": "prod_123" },
"select": {
"id": true,
"name": true,
"manufacturer": {
"select": { "id": true, "name": true }
}
}
}
}interface RQLResponse {
data: {
[queryKey: string]: any | null;
};
errors: RQLResponseError[];
}
interface RQLResponseError {
queryKey: string;
code: RQLErrorCode;
message: string;
details?: unknown;
}{
"data": {
"product": {
"id": "prod_123",
"name": "Laptop",
"manufacturer": { "id": "mfr_1", "name": "TechCorp" }
}
},
"errors": []
}| Code | Description |
|---|---|
CONTRACT_NOT_FOUND |
Requested contract does not exist |
INVALID_PARAMS |
Parameters failed Zod validation |
INVALID_SELECT |
Select contains unknown/forbidden fields |
INVALID_TEMPLATE |
Template reference is invalid or missing |
CYCLE_DETECTED |
Circular dependency in query templates |
BUDGET_EXCEEDED |
Query exceeds configured limits |
RESOLVER_ERROR |
Error during resolver execution |
INTERNAL_SERVER_ERROR |
Unexpected server error |
Used in relation params to reference parent object fields:
{{ parent.fieldName }}
Used in query params to reference completed query results:
{{ data.queryKey.fieldName }}
{{ data.queryKey.nested.path }}
Default limits (configurable):
| Limit | Default | Description |
|---|---|---|
maxDepth |
8 | Maximum relation nesting depth |
maxFields |
200 | Maximum fields per query |
maxBatchSize |
100 | Maximum items in batch call |
maxQueriesPerRequest |
25 | Maximum queries per payload |
interface RQLSchemaResponse {
contracts: RQLContractDefinition[]; // Ungrouped contracts
groups: {
name: string;
description: string;
contractCount: number;
}[];
}interface RQLContractDefinition {
name: string;
description: string;
type: 'GET' | 'POST' | 'UPDATE' | 'DELETE' | 'ACTION';
params: object; // JSON Schema
selectable: Record<string, {
type: string;
description: string;
optional?: boolean;
selectable?: Record<string, any>; // For relations
}>;
group?: string;
}When a relation has batch metadata:
relation: {
contractName: "getManufacturerById",
params: { manufacturerId: "{{ parent.manufacturerId }}" },
batch: { param: "manufacturerId", as: "manufacturerIds" }
}The engine will:
- Collect all unique
manufacturerIdvalues from parents - Make a single call with
{ manufacturerIds: ["mfr_1", "mfr_2", ...] } - Map results back to each parent
This prevents N+1 queries automatically.