Skip to main content

JSON API

In addition to server-rendered HTML pages, our application provides a RESTful JSON API. This is useful for building mobile apps or single-page applications (SPAs) that need to interact with the same data.

Prerequisites

What You’ll Learn

  • How to expose CRUD endpoints with Ormed-backed handlers
  • How DTOs shape API write payloads
  • How to share model logic between web and API surfaces

Step Outcome

By the end of this page, you should have:

  • Stable JSON contracts for movie and genre resources
  • Clear status-code behavior for success, validation failure, and missing resources
  • DTO-backed write handlers with minimal parsing/validation boilerplate

Movie endpoints

The API endpoints use the same database logic as the web handlers but return JSON responses instead of HTML.

Fetches a list of movies. We use jsonEncode to convert the model list to a JSON string.

    final movies = await database.dataSource
.query<$Movie>()
.withRelation('genre')
.orderBy('createdAt', descending: true)
.get();

return _json({'movies': movies.map(_movieViewModel).toList()});

Movie API contract (summary)

EndpointSuccessCommon failures
GET /api/movies200
GET /api/movies/:id200404 when not found
POST /api/movies201400 validation / malformed JSON
PATCH /api/movies/:id200400 invalid payload, 404 missing
DELETE /api/movies/:id200404 missing

Genre endpoints

    final genres = await database.dataSource
.query<$Genre>()
.orderBy('name')
.get();
return _json({'genres': genres.map(_genreViewModel).toList()});

Error Shape

Handlers in this tutorial return explicit JSON for failure modes. Typical responses are:

  • {"error": "Movie not found"} for missing records
  • {"errors": [...]} for validation failures

Payload Format

All API payloads use the field names defined in your models. For example, when creating a movie, the JSON should look like this:

{
"title": "Inception",
"releaseYear": 2010,
"summary": "A thief who steals corporate secrets through the use of dream-sharing technology.",
"genreId": 1
}

Quick Manual Check

curl -s http://localhost:8080/api/movies | jq
curl -s http://localhost:8080/api/genres | jq