Projections and Services Let's add the service to fetch a question by its id. Service Read operations translate to the verb when using http. We'll be able to to fetch the Question with id 1. The response will be json. The return multiplicity is one, so the response body will be a json object, not a json array. The criteria matches against the path parameter , like the sql The projection defines how much data will get serialized in the response body. Projection The service referred to the projection without defining it. Let's do that now. This projection includes everything; all of the question's properties including its answers, and all of the answers' properties. We do want everything included in the service's json response, but if we didn't we could remove parts to shrink the response. JSON Format Since the service definition includes , the response body will match the nested structure of the projection, and the projection's header names will be ignored. CSV Format If the service definition included instead, then the nested structure would be flattened and the header names would become column headers in the response. The order of the columns would be defined by the order they appear in the projection definition from top-to-bottom, which is depth-first. Note that to-many association ends get flattened, so the data for question 1 appears twice. service QuestionResource { read getById(questionId: Long[1..1] id path): QuestionReadProjection[1] { url : /question/{questionId: Long[1..1] id}; criteria : this.id == questionId; format : json; } } GET GET /api/question/1 Question.id questionId where q.id = ? QuestionReadProjection projection QuestionReadProjection on Question { id: "Question id", title: "Question title", body: "Question body", answers: { id: "Answer id", body: "Answer body", }, } format: json format: csv "Question id", "Question title" , "Question body" , "Answer id", "Answer body" 1, "Question title 1", "Question body 1", 1, "Answer body 1" 1, "Question title 1", "Question body 1", 2, "Answer body 2"