Mastering Drupal-Flutter Integration: Create Your Custom API

Profile picture for user Mustafa Salameh
Mustafa Salameh

Hey there, tech enthusiasts and savvy developers! Today, we're diving into the world of Drupal and Flutter integration. Whether you're a Drupal veteran or a Flutter aficionado, this guide is your ticket to creating custom APIs like a pro. So, grab your favorite cup of coffee, and let's get started!


Drupal-Flutter Integration: How to Create your Custom API with Ease

1. Setting Up Your Drupal Stage

First things first, let's get your Drupal site ready. We're creating a Content Type Event, which is like setting the stage for our main act - the custom API. It's simple: head to your Drupal, create a content type, and you're off to a great start.


2. Crafting Your Custom Module in Drupal

Now, let's roll up our sleeves and create a custom module. Navigate to \web\modules\custom, create a folder named sample_rest_resource, and add these basic files:

  • sample_rest_resource.module

This is where you define the nuts and bolts of your module. Think of it as laying the foundation for your custom API.

Related: Creating Custom Functionality in Drupal 10


Crafting custom modules in Drupal 10


3. Structuring Your Module Like a Pro

Organize your module with an intuitive folder structure. Create a path src\Plugin\rest\resource and add a PHP file AddEvent.php. This structure keeps things neat and accessible.


Creating a folder structure


4. The Heart of Your Module: AddEvent.php

Here's where the magic happens. Your AddEvent.php is the core of your custom API. It's a PHP class handling the POST requests from your Flutter app. Keep this code updated and error-free.

namespace Drupal\sample_rest_resource\Plugin\rest\resource;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
use Psr\Log\LoggerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\node\Entity\Node;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

 * Provides a resource to get view modes by entity and bundle.
 * @RestResource(
 *   id = "custom_get_rest_resource",
 *   label = @Translation("Custom Event Rest Resource"),
 *   uri_paths = {
 *     "create" = "/api/v1/create-event"
 *   }
 * )

Tip: Make sure your code is clean, well-commented, and adheres to the latest Drupal standards.


5. Creating Your Class SampleGetRestResource

Now, its time to create our class SampleGetRestResource. Check out how in our code snippet below:

class SampleGetRestResource extends ResourceBase

     * A current user instance which is logged in the session.
     * @var \Drupal\Core\Session\AccountProxyInterface

    protected $loggedUser;
     * Constructs a Drupal\rest\Plugin\ResourceBase object.
     * @param array $configuration
     *   A configuration array containing information about the plugin instance.
     * @param string $plugin_id
     *   The plugin_id for the plugin instance.
     * @param mixed $plugin_definition
     *   The plugin implementation definition.
     * @param array $serializer_formats
     *   The available serialization formats.
     * @param \Psr\Log\LoggerInterface $logger
     *   A logger instance.
     * @param \Drupal\Core\Session\AccountProxyInterface $account
     *   The current user.

   public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger, AccountProxyInterface $account)
        parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);

        $this->account = $account;

     * {@inheritdoc}

    public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition)
        return new static(
     * Responds to entity Post requests.
     * @return \Drupal\rest\ResourceResponse

    public function post(array $data = [])

        // Ensure required data is present.
        if (empty($data['title'])) {
            throw new BadRequestHttpException('Title is required.');

        // Create the node.
        $node = Node::create([
            'type' => 'event',
            'title' => $data['title'], // title Field

        try {
        catch (\Exception $e) {
            throw new HttpException(500, 'Internal Server Error');
        return new ResourceResponse(['message' => 'Event created successfully']);


6. Activating Your Custom Rest Resource

Head over to /admin/modules in Drupal, find 'Sample Rest Resource', and click 'Install'. It's like turning the key to start your engine.


Activating Sample Rest Resource


7. Enabling Essential Drupal Modules

Don't forget to enable the 'RESTful Web Service' and 'Rest UI' modules in Drupal. These are crucial for your API to communicate effectively.


Enabling essential drupal modules


8. Configuring Through Rest UI

Navigate to /admin/config/services/rest, enable 'Custom Event Rest Resource', and set 'Accepted request formats' to JSON, with 'basic_auth' as the authentication provider. It's like setting the rules of engagement for your API.


Configuring through Rest API


9. Flutter Side: Prepping for Success

Moving to Flutter, begin by adding the 'http' package to your pubspec.yaml file. This package is your key to API communication.

    sdk: flutter
  http: ^0.13.3


10. The Flutter Code: Making the POST Request

Time to write some Flutter code. This Dart snippet demonstrates how to make a POST request to your Drupal API. Remember, error handling and JSON parsing are crucial.

Code sample for POST requests

import 'package:http/http.dart' as http;

void  postRequest(String title) async {
    String apiUrl = "";
    Map<String, dynamic> jsonData ={
      "title": "${title}"
    String username = "mustafa";
    String password = "1234";
    String jsonBody = json.encode(jsonData);
    String basicAuth = 'Basic ' + base64Encode(utf8.encode('$username:$password'));

    try {
      final response = await
        headers: {
          'Content-Type': 'application/json',
          'Authorization': basicAuth,
        body: jsonBody,

      if (response.statusCode == 200) {
        print("Request successful: ${response.body}");
      } else {
        print("Request failed with status: ${response.statusCode}");
        print("Response body: ${response.body}");
    } catch (e) {
      print("Error: $e");

Tip: Ensure your code is efficient, handles errors gracefully, and parses JSON data accurately.


11. Crafting the User Interface in Flutter

Create a simple yet effective UI in Flutter with a TextField and an ElevatedButton. This interface allows users to input data and send it to Drupal.

 Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('node Page Event '),
        body: Container(
            padding: const EdgeInsets.all(25.0),
            child: Column(
              children: [
                  controller: mycontroller,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: 'Add Title',
                const SizedBox(height: 25,),
                    onPressed: () {
                      mycontroller.text= "";
                    child: Text("Create  Event"))


12. The Final Touch: Sending Data

Finally, let users send data through the Flutter app. For example, they can input an event title, tap 'Create Event', and voila! The event is created in your Drupal CMS.



And there you have it! A step-by-step guide to creating a custom API in Drupal and integrating it with a Flutter application. Remember, the key to success is in the details - organized code, clear instructions, and user-friendly interfaces.

Interested in more Drupal-Flutter insights? Check out Drupal Community Forums and Flutter's community for advanced tips and tricks.

Happy coding, and I'll see you in the next guide!

Additional Reading: