Accepted path shapes

A path is interpreted structurally, not as a pattern language - only these four shapes are accepted (each segment is either a plain literal or a single {paramName} placeholder; nothing else, so the path can never allow arbitrary execution, filesystem access, or client-controlled query logic):

ShapeExampleMeaning
/literal/usersPlain collection - typeId's own routeName.
/literal/{'{'}param{'}'}/users/{'{'}id{'}'}Plain record - requires lookupField.
/literal/{'{'}param{'}'}/literal/team/{'{'}id{'}'}/playersNested collection - requires relationshipId.
/literal/{'{'}param{'}'}/literal/{'{'}param{'}'}/team/{'{'}id{'}'}/players/{'{'}playerId{'}'}Nested record - requires both.

The literal segment representing this route's own type must equal that type's routeName (the third segment for a nested route, otherwise the first). For a nested route, the first segment must equal the related parent type's routeName - this is exactly what routeName exists for (see Data Types docs).

GET
/admin/projects/{projectId}/routes
List routes

Returns every route configured in the Project. Requires any effective Project role (viewer included).

Example response

{
  "routes": [
    {
      "id": 1,
      "method": "GET",
      "path": "/users",
      "typeId": 1
    },
    {
      "id": 2,
      "method": "GET",
      "path": "/users/{id}",
      "typeId": 1,
      "lookupField": "id"
    },
    {
      "id": 3,
      "method": "GET",
      "path": "/users/{id}/posts",
      "typeId": 2,
      "relationshipId": 1
    }
  ]
}
POST
/admin/projects/{projectId}/routes
Create a route

Creates a runtime route. Requires effective Project editor or admin. typeId must belong to this Project. lookupField is required exactly when the path ends in a {param} (a record route), and must be that type's configured identifier or another unique field. relationshipId is required exactly when the path is nested, and must be a relationship whose source (child) type is this route's typeId and whose target (parent) type's routeName matches the path's first segment. An optional boolean requiresAuth gates this specific route behind a Bearer token - only settable once the Project has a Runtime Auth type configured (422 otherwise); see Runtime Auth docs.

Request (nested example)

{
  "method": "GET",
  "path": "/users/{id}/posts",
  "typeId": 2,
  "relationshipId": 1
}

Response (201)

{
  "id": 3,
  "method": "GET",
  "path": "/users/{id}/posts",
  "typeId": 2,
  "relationshipId": 1,
  "requiresAuth": false
}

Returns 422 for a malformed path, an unknown typeId/relationshipId, a segment that doesn't match the expected routeName, an invalid lookupField, or a relationshipId whose source type isn't this route's typeId. Returns 409 if this exact (method, path) already exists in the Project.

PUT
/admin/projects/{projectId}/routes/{routeId}
Replace a route

Fully replaces the route - same request shape and validation as create. Requires effective Project editor or admin. Changes take effect for subsequent runtime requests immediately; existing template data and API-key dataset instances are untouched, since routes only control access to data, not its contents.

DELETE
/admin/projects/{projectId}/routes/{routeId}
Delete a route

Removes the route. Requires effective Project editor or admin. Subsequent runtime requests to that method and path return 404. Does not delete any records, data types, relationships, template data, or API keys - it only removes that means of accessing them.