Back to blog
12 September 2025Nicolas Dabène — Développeur Full Stack & Orchestrateur IA chez Profileo , 77-24 e-commerce hosting et Zentria3 min

Contribute to PrestaShop 9 Admin API

PrestaShop & e-commercePrestaShopLLM & modelesSecuriteAPI
Contents

Mind map of 8 essential concepts for PrestaShop 9 Admin API

RSS

RSS sends new articles to the reader of your choice, without an algorithm or newsletter.

Open RSS feed

Contributing to PrestaShop 9’s new Admin API can seem intimidating. We read words like CQRS, API Platform, OAuth2… and many developers think:

“Wow, I’ll need to follow weeks of training before laying my first brick.”

Actually, it’s false ✅ With only 8 well-understood concepts, you can create a functional endpoint in less than an hour.

In this guide, I’ll explain each building block as if we were together in a classroom: I set the context, illustrate with a concrete example, then we move forward step by step.


1. #[ApiResource]: The Magic Label

Imagine a library. As long as a book doesn’t have a barcode, impossible to borrow it.

In PrestaShop, this barcode is #[ApiResource]. It tells API Platform: “This class is a resource exposed by the API.”

  • Without it → the class remains invisible
  • With it → it becomes a REST entry point

📚 Read official ApiResource doc


2. CQRSGet and CQRSCreate: Separating Reading and Acting

PrestaShop 9 applies a clear discipline:

  • Reading data → role of Queries
  • Modifying data → role of Commands

👉 This is the CQRS pattern (Command Query Responsibility Segregation).

Concretely:

  • CQRSGet → “When doing a GET, execute this Query.”
  • CQRSCreate → “When doing a POST, execute this Command, then return the result thanks to this Query.”

📚 Learn more about CQRS in PrestaShop


3. URI Templates: Your Resources’ Address

Each resource needs a readable and structured address.

<span class="s1">'/products/{productId}'</span>

➡️ Here, the API responds to /products/123 with 123 as parameter.

You can nest multiple levels:

/categories/{categoryId}/products/{productId}

👉 Think of it as a city map: your URIs are the streets where developers will navigate.

📚 Doc on API Resources


4. DTOs: Data Bags

A DTO (Data Transfer Object) = a backpack 🎒 It does nothing by itself, just transports data.

Minimalist example:

<span class="kd">class</span> <span class="nc">Product</span> <span class="p">{</span>
    <span class="k">public</span> <span class="kt">int</span> <span class="nv">$id</span><span class="p">;</span>
    <span class="k">public</span> <span class="kt">string</span> <span class="nv">$name</span><span class="p">;</span>
<span class="p">}</span>

No business logic here. 👉 All intelligence already lives in your Commands and Queries.


5. OAuth Scopes: Access Badges

An API is an open door. But who has the right to enter? The answer: OAuth2 scopes.

Each operation declares necessary permissions. Examples:

  • product_read → read products
  • product_write → modify products

See them as company access badges. Without the right badge → no entry.

📚 Admin API OAuth doc


6. Requirements: Filtering at the Door

An endpoint /products/{productId} must receive a numeric identifier. But what if someone sends /products/abc?

👉 Add a requirement:

<span class="n">requirements</span><span class="o">:</span> <span class="p">[</span><span class="s1">'productId'</span> <span class="o">=></span> <span class="s1">'\\d+'</span><span class="p">]</span>

Result: only URLs with a number (/products/123) are accepted. It’s the bouncer at the nightclub entrance: wrong outfit → no entry.


7. The Identifier: Your Resource’s ID Card

API Platform must know which field represents the unique identifier. Otherwise, impossible to properly manage your resources.

So we add:

<span class="c1">#[ApiProperty(identifier: true)]</span>
<span class="k">public</span> <span class="kt">int</span> <span class="nv">$id</span><span class="p">;</span>

Only one field must play this role. 👉 It’s your resource’s social security number.


8. Organization: One Folder per Entity

Last concept: a bit of discipline! In ps_apiresources, each resource lives in its folder:

ps_apiresources/src/ApiPlatform/Resources/Product/

👉 Like a well-organized backpack: one subject = one notebook, one resource = one folder.

📚 Explore ps_apiresources GitHub repo


Concrete Example: Product Resource

<span class="cp"><?php</span>
<span class="kn">namespace</span> <span class="nn">PrestaShop\Module\APIResources\ApiPlatform\Resources\Product</span><span class="p">;</span>

<span class="kn">use</span> <span class="nc">ApiPlatform\Metadata\ApiResource</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">ApiPlatform\Metadata\ApiProperty</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">PrestaShopBundle\ApiPlatform\Metadata\CQRSGet</span><span class="p">;</span>
<span class="kn">use</span> <span class="nc">PrestaShopBundle\ApiPlatform\Metadata\CQRSCreate</span><span class="p">;</span>

<span class="c1">#[ApiResource(</span>
    <span class="n">operations</span><span class="o">:</span> <span class="p">[</span>
        <span class="k">new</span> <span class="nc">CQRSGet</span><span class="p">(</span>
            <span class="n">uriTemplate</span><span class="o">:</span> <span class="s1">'/products/{productId}'</span><span class="p">,</span>
            <span class="n">requirements</span><span class="o">:</span> <span class="p">[</span><span class="s1">'productId'</span> <span class="o">=></span> <span class="s1">'\\d+'</span><span class="p">],</span>
            <span class="nc">CQRSQuery</span><span class="o">:</span> <span class="nc">GetProductForEditing</span><span class="o">::</span><span class="n">class</span><span class="p">,</span>
            <span class="n">scopes</span><span class="o">:</span> <span class="p">[</span><span class="s1">'product_read'</span><span class="p">]</span>
        <span class="p">),</span>
        <span class="k">new</span> <span class="nc">CQRSCreate</span><span class="p">(</span>
            <span class="n">uriTemplate</span><span class="o">:</span> <span class="s1">'/products'</span><span class="p">,</span>
            <span class="nc">CQRSCommand</span><span class="o">:</span> <span class="nc">AddProductCommand</span><span class="o">::</span><span class="n">class</span><span class="p">,</span>
            <span class="nc">CQRSQuery</span><span class="o">:</span> <span class="nc">GetProductForEditing</span><span class="o">::</span><span class="n">class</span><span class="p">,</span>
            <span class="n">scopes</span><span class="o">:</span> <span class="p">[</span><span class="s1">'product_write'</span><span class="p">]</span>
        <span class="p">)</span>
    <span class="p">]</span>
<span class="p">)]</span>
<span class="kd">class</span> <span class="nc">Product</span>
<span class="p">{</span>
    <span class="c1">#[ApiProperty(identifier: true)]</span>
    <span class="k">public</span> <span class="kt">int</span> <span class="nv">$productId</span><span class="p">;</span>

    <span class="k">public</span> <span class="kt">string</span> <span class="nv">$name</span><span class="p">;</span>
    <span class="k">public</span> <span class="kt">float</span> <span class="nv">$price</span><span class="p">;</span>
    <span class="k">public</span> <span class="kt">bool</span> <span class="nv">$active</span><span class="p">;</span>
<span class="p">}</span>


Tip: “Cheating” with Existing Commands and Queries

The secret? No need to reinvent everything: most Commands and Queries already exist in PrestaShop core!

To discover them:

php bin/console prestashop:list:commands-and-queries

Examples:

  • AddProductCommand / GetProductForEditing
  • AddCategoryCommand / GetCategoryForEditing
  • AddCustomerCommand / GetCustomerForEditing

📚 Official Commands/Queries list


How to Start Today?

  1. Join Slack #cfc-adminapi to ask your questions.
  2. Explore existing resources in ps_apiresources.
  3. Copy the template above, adapt it, propose a Pull Request.

Conclusion: Learning by Walking

Many hesitate to contribute because they believe they must master everything before starting. The truth: we learn by contributing.

With these 8 simple concepts, you already have the keys to write an endpoint. Advanced notions (State Providers, Processors, Serialization Groups…) will come naturally with practice.

👉 The best time to start was yesterday. The second best time is today.


🔗 Useful Resources


Article published on September 12, 2025 by Nicolas Dabène - PrestaShop Expert & open source contributor since 2010.

Nicolas Dabène

Author

Nicolas Dabène

Développeur Full Stack & Orchestrateur IA chez Profileo , 77-24 e-commerce hosting et Zentria

Senior PHP/Laravel developer with 12+ years of experience in e-commerce. Specialised in PrestaShop architecture, AI agents and automation.

RSS

Follow this blog

RSS sends new articles to the reader of your choice, without an algorithm or newsletter.

I want a simple setup

Choose a reader, add the feed, then every new article appears there automatically.

  1. 1. Pick one of the readers below.
  2. 2. Open it and add this feed URL.
  3. 3. Read the next articles from one place.