What is Crudful?

Crudful provides predefined services to improve mobile and frontend developers' learning journeys. Working with web services can be a daunting task, so we are trying to keep all Crudful services as simple as possible.

Here are some general design decisions we took during the implementation of the services.

Architecture

Crudful embraces REST architectural style, which is the most common architecture for years, to provide web services. Since RESTful services work with the standard HTTP request methods, you can develop applications with all languages, frameworks and libraries.

Authentication

It is a common practice to authenticate requests using HTTP headers, which can provide additional information about a request or response.

All Crudful endpoints require cfAccessKey to be in the incoming requests' header, its value can be found on the Account page.

// Don't forget to replace `3a4efdb166e747d481dfd9887c638afcf5f10465` with your own key
const cfAccessKey = "3a4efdb166e747d481dfd9887c638afcf5f10465";
// Get tasks
fetch("https://todo.crudful.com/tasks", {
method: "GET",
headers: {
cfAccessKey: cfAccessKey,
},
})
.then((response) => response.json())
.then((json) => console.log(json));

Data Format

Since JSON is used as the main data-interchange format, don't forget to set Content-Type header to application/json in your requests. Note that some libraries automatically set Content-Type header to application/json, when the request body is a JSON.

// Don't forget to replace `3a4efdb166e747d481dfd9887c638afcf5f10465` with your own key
const cfAccessKey = "3a4efdb166e747d481dfd9887c638afcf5f10465";
const contentType = "application/json";
// Prepare task data
const taskData = {
title: "Learn React",
details:
"Read the documentation at https://reactjs.org/docs/getting-started.html",
due: "2020-06-23T08:41:44.646Z",
isCompleted: false,
};
// Create a task
fetch("https://todo.crudful.com/tasks", {
method: "POST",
headers: {
cfAccessKey: cfAccessKey,
"Content-Type": contentType,
},
body: JSON.stringify(taskData), // convert task data to JSON string
})
.then((response) => response.json())
.then((json) => console.log(json));

Date and Time

Even though there are several different approaches to work with dates, Crudful services prefer ISO 8601 standard, which is a human-readable form, to represent dates.

The exact form is YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z] and it should contain at least year, month, day, hour and minute. On the other hand, second, microsecond and time zone parts are optional. Some valid examples are:

  • 2020-09-25T18:00
  • 2020-09-25T18:00:46
  • 2020-09-25T18:00:46.123456
  • 2020-09-25T18:00:46+03:00
  • 2020-09-25T18:00:46-03:00
  • 2020-09-25T18:00:46Z

Base64 Encoding

Base64 encoding is a well-known method to handle file related fields in JSON based APIs. Crudful services accept the following formats:

  • /9j/4AAQSkZJRgABAQ...
  • data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...

Filtering

Applications generally display items after applying some filters like username, status and date. Crudful services filter objects through query parameters and filterable fields are presented in the Explorer tab.

  • Filters tasks under a specific list
    // Don't forget to replace `3a4efdb166e747d481dfd9887c638afcf5f10465` with your own key
    const cfAccessKey = "3a4efdb166e747d481dfd9887c638afcf5f10465";
    // Get tasks filtered by list id
    // Don't forget to replace `0dd127da-ecbd-47e4-98ba-ef1e8c6b5b41` with an existing list id
    fetch(
    "https://todo.crudful.com/tasks?listId=0dd127da-ecbd-47e4-98ba-ef1e8c6b5b41",
    {
    method: "GET",
    headers: {
    cfAccessKey: cfAccessKey,
    },
    }
    )
    .then((response) => response.json())
    .then((json) => console.log(json));
  • Filters uncompleted tasks under a specific list
    // Don't forget to replace `3a4efdb166e747d481dfd9887c638afcf5f10465` with your own key
    const cfAccessKey = "3a4efdb166e747d481dfd9887c638afcf5f10465";
    // Get tasks filtered by list id and is completed
    // Don't forget to replace `0dd127da-ecbd-47e4-98ba-ef1e8c6b5b41` with an existing list id
    fetch(
    "https://todo.crudful.com/tasks?listId=0dd127da-ecbd-47e4-98ba-ef1e8c6b5b41&isCompleted=false",
    {
    method: "GET",
    headers: {
    cfAccessKey: cfAccessKey,
    },
    }
    )
    .then((response) => response.json())
    .then((json) => console.log(json));

Ordering

List endpoints use ordering query parameter to sort the returning objects. Available ordering values are noted in the Explorer tab.

  • Sorts the tasks with respect to Task.createdAt field, starting from the smallest to largest
    // Don't forget to replace `3a4efdb166e747d481dfd9887c638afcf5f10465` with your own key
    const cfAccessKey = "3a4efdb166e747d481dfd9887c638afcf5f10465";
    // Get tasks in ascending order of created at
    fetch("https://todo.crudful.com/tasks?ordering=createdAt", {
    method: "GET",
    headers: {
    cfAccessKey: cfAccessKey,
    },
    })
    .then((response) => response.json())
    .then((json) => console.log(json));
  • Sorts the lists with respect to List.createdAt field, starting from the largest to smallest
    // Don't forget to replace `3a4efdb166e747d481dfd9887c638afcf5f10465` with your own key
    const cfAccessKey = "3a4efdb166e747d481dfd9887c638afcf5f10465";
    // Get lists in descending order of created at
    // `-` before `createdAt` changes the ordering
    fetch("https://todo.crudful.com/lists?ordering=-createdAt", {
    method: "GET",
    headers: {
    cfAccessKey: cfAccessKey,
    },
    })
    .then((response) => response.json())
    .then((json) => console.log(json));

Pagination

Some endpoints might not return all the resulting objects at once. Pagination is a common approach to divide large result sets into small pieces.

Crudful services support limit-offset pagination in the list endpoints. Therefore, API consumers should use offset, which indicates the starting position, and limit, which specifies the maximum number of objects to return, query parameters to get the paginated data.

  • Returns first ten tasks
    // Don't forget to replace `3a4efdb166e747d481dfd9887c638afcf5f10465` with your own key
    const cfAccessKey = "3a4efdb166e747d481dfd9887c638afcf5f10465";
    // Get first ten tasks
    fetch("https://todo.crudful.com/tasks?limit=10", {
    method: "GET",
    headers: {
    cfAccessKey: cfAccessKey,
    },
    })
    .then((response) => response.json())
    .then((json) => console.log(json));
  • Skips first five lists and returns next ten lists
    // Don't forget to replace `3a4efdb166e747d481dfd9887c638afcf5f10465` with your own key
    const cfAccessKey = "3a4efdb166e747d481dfd9887c638afcf5f10465";
    // Get ten lists after skipping five
    fetch("https://todo.crudful.com/lists?limit=10&offset=5", {
    method: "GET",
    headers: {
    cfAccessKey: cfAccessKey,
    },
    })
    .then((response) => response.json())
    .then((json) => console.log(json));

Please note that the next and previous fields in the responses have helpful URLs for the pagination.